forked from boostorg/utility
Compare commits
19 Commits
esp-idf-co
...
string_vie
Author | SHA1 | Date | |
---|---|---|---|
c23afeb687 | |||
715ee69717 | |||
404fea073f | |||
98b24e1406 | |||
090ab12074 | |||
904e2c3c81 | |||
270a6c39b5 | |||
6069151a06 | |||
9c961f0577 | |||
268861ff6b | |||
a329164f8c | |||
61c02fdd7a | |||
896577a68d | |||
24933c4409 | |||
6c5a955c85 | |||
306bbfdaf1 | |||
250aaa73e8 | |||
57d2173de9 | |||
20b78d7667 |
@ -117,3 +117,22 @@ boostbook standalone_string_ref
|
||||
# How far down we go with TOC's
|
||||
<xsl:param>generate.section.toc.level=1
|
||||
;
|
||||
|
||||
xml string_view : string_view.qbk ;
|
||||
boostbook standalone_string_view
|
||||
:
|
||||
string_view
|
||||
:
|
||||
# File name of HTML output:
|
||||
<xsl:param>root.filename=string_view
|
||||
# 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
|
||||
;
|
||||
|
381
doc/html/string_view.html
Normal file
381
doc/html/string_view.html
Normal file
@ -0,0 +1,381 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
|
||||
<title>String_View</title>
|
||||
<link rel="stylesheet" href="../../../../doc/src/boostbook.css" type="text/css">
|
||||
<meta name="generator" content="DocBook XSL Stylesheets V1.77.1">
|
||||
<link rel="home" href="string_view.html" title="String_View">
|
||||
</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_view"></a>String_View</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 class="author"><h3 class="author">
|
||||
<span class="firstname">Beman</span> <span class="surname">Dawes</span>
|
||||
</h3></div>
|
||||
</div></div>
|
||||
<div><p class="copyright">Copyright © 2012 Marshall Clow</p></div>
|
||||
<div><p class="copyright">Copyright © 2015 Beman Dawes</p></div>
|
||||
<div><div class="legalnotice">
|
||||
<a name="string_view.legal"></a><p>
|
||||
Distributed under the Boost Software License, Version 1.0. <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_view.html#string_view.overview">Overview</a></span></dt>
|
||||
<dt><span class="section"><a href="string_view.html#string_view.examples">Examples</a></span></dt>
|
||||
<dt><span class="section"><a href="string_view.html#string_view.reference">Reference </a></span></dt>
|
||||
<dt><span class="section"><a href="string_view.html#string_view.compiler_support">Compiler Support</a></span></dt>
|
||||
<dt><span class="section"><a href="string_view.html#string_view.history">History</a></span></dt>
|
||||
</dl>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_view.overview"></a><a class="link" href="string_view.html#string_view.overview" title="Overview">Overview</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Boost.StringView is an implementation of <code class="computeroutput"><span class="identifier">string_view</span></code>
|
||||
as specified in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#string.view" target="_top">N4480:
|
||||
ISO/IEC DTS 19568, Technical Specification - C++ Extensions for Library Fundamentals</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_view</span></code> is designed to
|
||||
solve these efficiency problems. A <code class="computeroutput"><span class="identifier">string_view</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_view</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_view</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_view</span></code>
|
||||
is cheap to create and cheap to copy.
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_view</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_view</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">&</span></code>
|
||||
with <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_view</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_view</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_view</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_view</span></code> refers to exists as long as the
|
||||
<code class="computeroutput"><span class="identifier">string_view</span></code> does.
|
||||
</p>
|
||||
<p>
|
||||
Note: The header actually contains a class template, <code class="computeroutput"><span class="identifier">basic_string_view</span></code>
|
||||
and four typedefs:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">charT</span><span class="special">,</span> <span class="keyword">class</span> <span class="identifier">traits</span> <span class="special">=</span> <span class="identifier">char_traits</span><span class="special"><</span><span class="identifier">charT</span><span class="special">>></span>
|
||||
<span class="keyword">class</span> <span class="identifier">basic_string_view</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">typedef</span> <span class="identifier">basic_string_view</span><span class="special"><</span><span class="keyword">char</span><span class="special">></span> <span class="identifier">string_view</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">basic_string_view</span><span class="special"><</span><span class="keyword">char16_t</span><span class="special">></span> <span class="identifier">u16string_view</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">basic_string_view</span><span class="special"><</span><span class="keyword">char32_t</span><span class="special">></span> <span class="identifier">u32string_view</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">basic_string_view</span><span class="special"><</span><span class="keyword">wchar_t</span><span class="special">></span> <span class="identifier">wstring_view</span><span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
So you can have views of strings of any of the four built-in character types
|
||||
as well as strings of user-defined character-like type strings. For the sake
|
||||
of simple exposition, we concentrate on <code class="computeroutput"><span class="identifier">string_view</span></code>
|
||||
(i.e. <code class="computeroutput"><span class="keyword">char</span></code> strings) in this documentation.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_view.examples"></a><a class="link" href="string_view.html#string_view.examples" title="Examples">Examples</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
Integrating <code class="computeroutput"><span class="identifier">string_view</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">&</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_view</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">&</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="char">'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_view</span></code>:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_view</span> <span class="identifier">extract_part</span> <span class="special">(</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">string_view</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_view</span></code>s
|
||||
created, and two <code class="computeroutput"><span class="identifier">string_view</span></code>s
|
||||
copied, but those are cheap operations.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_view.reference"></a><a class="link" href="string_view.html#string_view.reference" title="Reference">Reference </a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
The header file "string_view.hpp" defines a class template <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">basic_string_view</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="keyword">char16_t</span></code>
|
||||
/ <code class="computeroutput"><span class="keyword">char32_t</span></code> .
|
||||
</p>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="preprocessor">#include</span> <span class="special"><</span><span class="identifier">boost</span><span class="special">/</span><span class="identifier">utility</span><span class="special">/</span><span class="identifier">string_view</span><span class="special">.</span><span class="identifier">hpp</span><span class="special">></span></code>
|
||||
</p>
|
||||
<p>
|
||||
Types:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">typedef</span> <span class="identifier">traits</span> <span class="identifier">traits_type</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">charT</span> <span class="identifier">value_type</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">pointer</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">const_pointer</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">reference</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</span> <span class="identifier">const_reference</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">const_pointer</span> <span class="identifier">const_iterator</span><span class="special">;</span> <span class="comment">// implementation defined</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">const_iterator</span> <span class="identifier">iterator</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">reverse_iterator</span><span class="special"><</span><span class="identifier">const_iterator</span><span class="special">></span> <span class="identifier">const_reverse_iterator</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">const_reverse_iterator</span> <span class="identifier">reverse_iterator</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">size_t</span> <span class="identifier">size_type</span><span class="special">;</span>
|
||||
<span class="keyword">typedef</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">ptrdiff_t</span> <span class="identifier">difference_type</span><span class="special">;</span>
|
||||
<span class="keyword">static</span> <span class="identifier">BOOST_CONSTEXPR_OR_CONST</span> <span class="identifier">size_type</span> <span class="identifier">npos</span> <span class="special">=</span> <span class="identifier">size_type</span><span class="special">(-</span><span class="number">1</span><span class="special">);</span>
|
||||
</pre>
|
||||
<p>
|
||||
Construction and copying:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_view</span> <span class="special">()</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span> <span class="comment">// Constructs empty string_view</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_view</span> <span class="special">(</span><span class="keyword">const</span> <span class="identifier">basic_string_view</span> <span class="special">&</span><span class="identifier">rhs</span><span class="special">)</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">basic_string_view</span><span class="special">&</span> <span class="keyword">operator</span><span class="special">=(</span><span class="keyword">const</span> <span class="identifier">basic_string_view</span> <span class="special">&</span><span class="identifier">rhs</span><span class="special">)</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">typename</span> <span class="identifier">Allocator</span><span class="special">></span>
|
||||
<span class="identifier">basic_string_view</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"><</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">>&</span> <span class="identifier">str</span><span class="special">)</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span> <span class="comment">// Ctor from std::string</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_view</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">// Ctor from NULL-terminated string</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="identifier">basic_string_view</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">// Ctor from pointer, length pair</span>
|
||||
</pre>
|
||||
<p>
|
||||
<code class="computeroutput"><span class="identifier">string_view</span></code> does not define
|
||||
a move constructor or a move-assignment operator because copying a <code class="computeroutput"><span class="identifier">string_view</span></code> is just as cheap as moving one
|
||||
would be.
|
||||
</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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="identifier">BOOST_NOEXCEPT</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">&</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="identifier">BOOST_CONSTEXPR</span> <span class="keyword">const</span> <span class="identifier">charT</span><span class="special">&</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">&</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">&</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="identifier">BOOST_NOEXCEPT</span> <span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Modifying the <code class="computeroutput"><span class="identifier">string_view</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="comment">// boost extension</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</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="identifier">BOOST_CXX14_CONSTEXPR</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>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="keyword">void</span> <span class="identifier">swap</span><span class="special">(</span><span class="identifier">basic_string_view</span><span class="special">&</span> <span class="identifier">s</span><span class="special">)</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
</pre>
|
||||
<p>
|
||||
Searching:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</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="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</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="keyword">const</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</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="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</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="keyword">const</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">rfind</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</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="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</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="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</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="keyword">const</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_first_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_last_of</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</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="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_last_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</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="keyword">const</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_last_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</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="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</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="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</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="keyword">const</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_first_not_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</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="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="identifier">npos</span><span class="special">)</span> <span class="keyword">const</span> <span class="identifier">BOOST_NOEXCEPT</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</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="keyword">const</span><span class="special">;</span>
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">size_type</span> <span class="identifier">find_last_not_of</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</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="identifier">BOOST_CONSTEXPR</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="comment">// boost extension</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">bool</span> <span class="identifier">starts_with</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span> <span class="comment">// boost extension</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</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="comment">// boost extension</span>
|
||||
<span class="identifier">BOOST_CONSTEXPR</span> <span class="keyword">bool</span> <span class="identifier">ends_with</span><span class="special">(</span><span class="identifier">basic_string_view</span> <span class="identifier">x</span><span class="special">)</span> <span class="keyword">const</span> <span class="special">;</span> <span class="comment">// boost extension</span>
|
||||
</pre>
|
||||
<p>
|
||||
String-like operations:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Allocator</span><span class="special">></span> <span class="comment">// Only present if compiler supports C++11 explicit conversion</span>
|
||||
<span class="keyword">explicit</span> <span class="keyword">operator</span> <span class="identifier">basic_string</span><span class="special"><</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">>()</span> <span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="keyword">template</span><span class="special"><</span><span class="keyword">class</span> <span class="identifier">Allocator</span> <span class="special">=</span> <span class="identifier">allocator</span><span class="special"><</span><span class="identifier">charT</span><span class="special">></span> <span class="special">></span> <span class="comment">// Default only present if compiler supports</span>
|
||||
<span class="identifier">basic_string</span><span class="special"><</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">></span> <span class="comment">// C++11 default template parameters</span>
|
||||
<span class="identifier">to_string</span><span class="special">(</span><span class="keyword">const</span> <span class="identifier">Allocator</span><span class="special">&</span> <span class="identifier">a</span> <span class="special">=</span> <span class="identifier">Allocator</span><span class="special">())</span> <span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">size_type</span> <span class="identifier">copy</span><span class="special">(</span><span class="identifier">charT</span><span class="special">*</span> <span class="identifier">s</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">n</span><span class="special">,</span> <span class="identifier">size_type</span> <span class="identifier">pos</span> <span class="special">=</span> <span class="number">0</span><span class="special">)</span> <span class="keyword">const</span><span class="special">;</span>
|
||||
|
||||
<span class="identifier">BOOST_CXX14_CONSTEXPR</span> <span class="identifier">basic_string_view</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">// Create new string_view</span>
|
||||
</pre>
|
||||
<p>
|
||||
Comparison:
|
||||
</p>
|
||||
<pre class="programlisting"><span class="identifier">To</span> <span class="identifier">be</span> <span class="identifier">supplied</span>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_view.compiler_support"></a><a class="link" href="string_view.html#string_view.compiler_support" title="Compiler Support">Compiler Support</a>
|
||||
</h2></div></div></div>
|
||||
<p>
|
||||
This Boost implementation only requires a C++03 compliant compiler.
|
||||
</p>
|
||||
<p>
|
||||
The actual Library Fundamentals specification assumes a C++14 compliant compiler,
|
||||
so a few features are only present if actually supported by the compiler. Boost
|
||||
macros such as BOOST_CONSTEXPR, BOOST_CXX14_CONSTEXPR, and BOOST_NOEXCEPT supply
|
||||
certain features if supported by the compiler.
|
||||
</p>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="titlepage"><div><div><h2 class="title" style="clear: both">
|
||||
<a name="string_view.history"></a><a class="link" href="string_view.html#string_view.history" title="History">History</a>
|
||||
</h2></div></div></div>
|
||||
<h4>
|
||||
<a name="string_view.history.h0"></a>
|
||||
<span class="phrase"><a name="string_view.history.boost_1_53"></a></span><a class="link" href="string_view.html#string_view.history.boost_1_53">boost
|
||||
1.53</a>
|
||||
</h4>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||||
Introduced, based on 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>
|
||||
</li></ul></div>
|
||||
<h4>
|
||||
<a name="string_view.history.h1"></a>
|
||||
<span class="phrase"><a name="string_view.history.boost_1_60"></a></span><a class="link" href="string_view.html#string_view.history.boost_1_60">boost
|
||||
1.60</a>
|
||||
</h4>
|
||||
<div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">
|
||||
Updated to reflect <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#string.view" target="_top">N4480:
|
||||
ISO/IEC DTS 19568, Technical Specification - C++ Extensions for Library
|
||||
Fundamentals</a>
|
||||
</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: July 17, 2015 at 19:19:23 GMT</small></p></td>
|
||||
<td align="right"><div class="copyright-footer"></div></td>
|
||||
</tr></table>
|
||||
<hr>
|
||||
<div class="spirit-nav"></div>
|
||||
</body>
|
||||
</html>
|
243
doc/string_view.qbk
Normal file
243
doc/string_view.qbk
Normal file
@ -0,0 +1,243 @@
|
||||
[/
|
||||
/ Copyright (c) 2012 Marshall Clow
|
||||
/ Copyright (c) 2015 Beman Dawes
|
||||
/
|
||||
/ 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_View
|
||||
[quickbook 1.5]
|
||||
[authors [Clow, Marshall] [Dawes, Beman]]
|
||||
[copyright 2012 Marshall Clow, 2015 Beman Dawes]
|
||||
[license
|
||||
Distributed under the Boost Software License, Version 1.0.
|
||||
[@http://www.boost.org/LICENSE_1_0.txt]
|
||||
]
|
||||
]
|
||||
|
||||
[/===============]
|
||||
[section Overview]
|
||||
[/===============]
|
||||
|
||||
Boost.StringView is an implementation of `string_view` as specified in [@
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#string.view N4480:
|
||||
ISO/IEC DTS 19568, Technical Specification - C++ Extensions for Library Fundamentals].
|
||||
|
||||
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_view` is designed to solve these efficiency problems. A `string_view` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_view` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to.
|
||||
|
||||
A `string_view` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_view` is cheap to create and cheap to copy.
|
||||
|
||||
`string_view` 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_view` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_view`. Like `std::string`, `string_view` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end".
|
||||
|
||||
Because a `string_view` 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_view` refers to exists as long as the `string_view` does.
|
||||
|
||||
Note: The header actually contains a class template, `basic_string_view` and four typedefs:
|
||||
|
||||
template<class charT, class traits = char_traits<charT>>
|
||||
class basic_string_view;
|
||||
|
||||
typedef basic_string_view<char> string_view;
|
||||
typedef basic_string_view<char16_t> u16string_view;
|
||||
typedef basic_string_view<char32_t> u32string_view;
|
||||
typedef basic_string_view<wchar_t> wstring_view;
|
||||
|
||||
So you can have views of strings of any of the four built-in character types as well as strings of user-defined character-like type strings. For the sake of simple exposition, we concentrate on `string_view` (i.e. `char` strings) in this documentation.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/===============]
|
||||
[section Examples]
|
||||
[/===============]
|
||||
|
||||
Integrating `string_view` 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_view`.
|
||||
|
||||
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_view`:
|
||||
|
||||
boost::string_view extract_part ( boost::string_view 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_view`s created, and two `string_view`s copied, but those are cheap operations.
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
[/=================]
|
||||
[section:reference Reference ]
|
||||
[/=================]
|
||||
|
||||
The header file "string_view.hpp" defines a class template `boost::basic_string_view`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` .
|
||||
|
||||
`#include <boost/utility/string_view.hpp>`
|
||||
|
||||
Types:
|
||||
|
||||
typedef traits traits_type;
|
||||
typedef charT value_type;
|
||||
typedef charT* pointer;
|
||||
typedef const charT* const_pointer;
|
||||
typedef charT& reference;
|
||||
typedef const charT& const_reference;
|
||||
typedef const_pointer const_iterator; // implementation 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);
|
||||
|
||||
Construction and copying:
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view () BOOST_NOEXCEPT; // Constructs empty string_view
|
||||
BOOST_CONSTEXPR basic_string_view (const basic_string_view &rhs) BOOST_NOEXCEPT;
|
||||
basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT;
|
||||
template<typename Allocator>
|
||||
basic_string_view(const std::basic_string<charT, traits, Allocator>& str) BOOST_NOEXCEPT; // Ctor from std::string
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str); // Ctor from NULL-terminated string
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len); // Ctor from pointer, length pair
|
||||
|
||||
`string_view` does not define a move constructor or a move-assignment operator because copying a `string_view` is just as cheap as moving one would be.
|
||||
|
||||
Basic container-like functions:
|
||||
|
||||
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT ;
|
||||
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT ;
|
||||
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT ;
|
||||
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT ;
|
||||
|
||||
// All iterators are const_iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT ;
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT ;
|
||||
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT ;
|
||||
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT ;
|
||||
const_reverse_iterator rbegin() const BOOST_NOEXCEPT ;
|
||||
const_reverse_iterator crbegin() const BOOST_NOEXCEPT ;
|
||||
const_reverse_iterator rend() const BOOST_NOEXCEPT ;
|
||||
const_reverse_iterator crend() const BOOST_NOEXCEPT ;
|
||||
|
||||
Access to the individual elements (all of which are const):
|
||||
|
||||
BOOST_CONSTEXPR const charT& operator[](size_type pos) const ;
|
||||
BOOST_CONSTEXPR 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 BOOST_NOEXCEPT ;
|
||||
|
||||
Modifying the `string_view` (but not the underlying data):
|
||||
|
||||
void clear(); // boost extension
|
||||
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n);
|
||||
BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n);
|
||||
BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT;
|
||||
|
||||
Searching:
|
||||
|
||||
BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const;
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const;
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const;
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const;
|
||||
|
||||
BOOST_CONSTEXPR bool starts_with(charT c) const ; // boost extension
|
||||
BOOST_CONSTEXPR bool starts_with(basic_string_view x) const ; // boost extension
|
||||
BOOST_CONSTEXPR bool ends_with(charT c) const ; // boost extension
|
||||
BOOST_CONSTEXPR bool ends_with(basic_string_view x) const ; // boost extension
|
||||
|
||||
String-like operations:
|
||||
|
||||
template<class Allocator> // Only present if compiler supports C++11 explicit conversion
|
||||
explicit operator basic_string<charT, traits, Allocator>() const;
|
||||
|
||||
template<class Allocator = allocator<charT> > // Default only present if compiler supports
|
||||
basic_string<charT, traits, Allocator> // C++11 default template parameters
|
||||
to_string(const Allocator& a = Allocator()) const;
|
||||
|
||||
size_type copy(charT* s, size_type n, size_type pos = 0) const;
|
||||
|
||||
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos,
|
||||
size_type n=npos) const ; // Create new string_view
|
||||
|
||||
Comparison:
|
||||
|
||||
To be supplied
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section Compiler Support]
|
||||
[/===============]
|
||||
|
||||
This Boost implementation only requires a C++03 compliant compiler.
|
||||
|
||||
The actual Library Fundamentals specification assumes a C++14 compliant compiler, so a few features are only present if actually supported by the compiler. Boost macros such as BOOST_CONSTEXPR, BOOST_CXX14_CONSTEXPR, and BOOST_NOEXCEPT supply certain features if supported by the compiler.
|
||||
|
||||
[endsect]
|
||||
|
||||
[/===============]
|
||||
[section History]
|
||||
[/===============]
|
||||
|
||||
[heading boost 1.53]
|
||||
* Introduced, based on 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]
|
||||
|
||||
[heading boost 1.60]
|
||||
* Updated to reflect [@
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html#string.view N4480:
|
||||
ISO/IEC DTS 19568, Technical Specification - C++ Extensions for Library Fundamentals]
|
||||
|
||||
[endsect]
|
||||
|
||||
|
||||
|
||||
|
666
include/boost/utility/string_view.hpp
Normal file
666
include/boost/utility/string_view.hpp
Normal file
@ -0,0 +1,666 @@
|
||||
/*
|
||||
<20> Copyright (c) Marshall Clow 2012-2015.
|
||||
<20> Copyright Beman Dawes 2015
|
||||
|
||||
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
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_HPP
|
||||
#define BOOST_STRING_VIEW_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <boost/detail/workaround.hpp>
|
||||
#include <boost/utility/string_view_fwd.hpp>
|
||||
#include <boost/throw_exception.hpp>
|
||||
|
||||
#include <cstddef>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <iterator>
|
||||
#include <string>
|
||||
#include <cstring>
|
||||
#include <iosfwd>
|
||||
|
||||
namespace boost {
|
||||
|
||||
namespace detail {
|
||||
// A helper functor because sometimes we don't have lambdas
|
||||
template <typename charT, typename traits>
|
||||
class string_view_traits_eq {
|
||||
public:
|
||||
string_view_traits_eq ( charT ch ) : ch_(ch) {}
|
||||
bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
|
||||
charT ch_;
|
||||
};
|
||||
}
|
||||
|
||||
template<typename charT, typename traits> // traits defaulted in string_view_fwd.hpp
|
||||
class basic_string_view {
|
||||
public:
|
||||
// types
|
||||
typedef traits traits_type;
|
||||
typedef charT value_type;
|
||||
typedef charT* pointer;
|
||||
typedef const charT* const_pointer;
|
||||
typedef charT& reference;
|
||||
typedef const charT& const_reference;
|
||||
typedef const_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_view() BOOST_NOEXCEPT
|
||||
: ptr_(NULL), len_(0) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const basic_string_view &rhs) BOOST_NOEXCEPT
|
||||
: ptr_(rhs.ptr_), len_(rhs.len_) {}
|
||||
|
||||
basic_string_view& operator=(const basic_string_view &rhs) BOOST_NOEXCEPT {
|
||||
ptr_ = rhs.ptr_;
|
||||
len_ = rhs.len_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename Allocator>
|
||||
basic_string_view(const std::basic_string<charT, traits,
|
||||
Allocator>& str) BOOST_NOEXCEPT
|
||||
: ptr_(str.data()), len_(str.length()) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str)
|
||||
: ptr_(str), len_(traits::length(str)) {}
|
||||
|
||||
BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)
|
||||
: ptr_(str), len_(len) {}
|
||||
|
||||
// iterators
|
||||
BOOST_CONSTEXPR const_iterator begin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator cbegin() const BOOST_NOEXCEPT { return ptr_; }
|
||||
BOOST_CONSTEXPR const_iterator end() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
BOOST_CONSTEXPR const_iterator cend() const BOOST_NOEXCEPT { return ptr_ + len_; }
|
||||
const_reverse_iterator rbegin() const BOOST_NOEXCEPT { return const_reverse_iterator (end()); }
|
||||
const_reverse_iterator crbegin() const BOOST_NOEXCEPT { return const_reverse_iterator (end()); }
|
||||
const_reverse_iterator rend() const BOOST_NOEXCEPT { return const_reverse_iterator (begin()); }
|
||||
const_reverse_iterator crend() const BOOST_NOEXCEPT { return const_reverse_iterator (begin()); }
|
||||
|
||||
// capacity
|
||||
BOOST_CONSTEXPR size_type size() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type length() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT { return len_; }
|
||||
BOOST_CONSTEXPR bool empty() const BOOST_NOEXCEPT { return len_ == 0; }
|
||||
|
||||
// element access
|
||||
BOOST_CONSTEXPR const_reference operator[](size_type pos) const { return ptr_[pos]; }
|
||||
|
||||
BOOST_CONSTEXPR const_reference at(size_t pos) const {
|
||||
if ( pos >= len_ )
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_view::at" ) );
|
||||
return ptr_[pos];
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR const_reference front() const { return ptr_[0]; }
|
||||
BOOST_CONSTEXPR const_reference back() const { return ptr_[len_-1]; }
|
||||
BOOST_CONSTEXPR const_pointer data() const BOOST_NOEXCEPT { return ptr_; }
|
||||
|
||||
// modifiers
|
||||
void clear() BOOST_NOEXCEPT { len_ = 0; } // Boost extension
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_prefix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
ptr_ += n;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void remove_suffix(size_type n) {
|
||||
if ( n > len_ )
|
||||
n = len_;
|
||||
len_ -= n;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR void swap(basic_string_view& s) BOOST_NOEXCEPT {
|
||||
std::swap(ptr_, s.ptr_);
|
||||
std::swap(len_, s.len_);
|
||||
}
|
||||
|
||||
|
||||
// basic_string_view string operations
|
||||
|
||||
#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>(begin(), end());
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_FUNCTION_TEMPLATE_DEFAULT_ARGS
|
||||
template<typename Allocator = std::allocator<charT> >
|
||||
std::basic_string<charT, traits> to_string(const Allocator& a = Allocator()) const {
|
||||
return std::basic_string<charT, traits, Allocator>(begin(), end(), a);
|
||||
}
|
||||
#else
|
||||
std::basic_string<charT, traits> to_string() const {
|
||||
return std::basic_string<charT, traits>(begin(), end());
|
||||
}
|
||||
#endif
|
||||
|
||||
size_type copy( charT* s, size_type n, size_type pos = 0 ) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::copy" ) );
|
||||
size_type rlen = (std::min)(n, len_ - pos);
|
||||
// use std::copy(begin() + pos, begin() + pos + rlen, s) rather than
|
||||
// std::copy_n(begin() + pos, rlen, s) to support pre-C++11 standard libraries
|
||||
std::copy(begin() + pos, begin() + pos + rlen, s);
|
||||
return rlen;
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const {
|
||||
if ( pos > size())
|
||||
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
|
||||
if ( n == npos || pos + n > size())
|
||||
n = size () - pos;
|
||||
return basic_string_view ( data() + pos, n );
|
||||
}
|
||||
|
||||
BOOST_CXX14_CONSTEXPR int compare(basic_string_view x) const BOOST_NOEXCEPT {
|
||||
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 );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, basic_string_view x)
|
||||
const BOOST_NOEXCEPT {
|
||||
return substr(pos1, n1).compare(x);
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
basic_string_view x, size_type pos2, size_type n2) const {
|
||||
return substr(pos1, n1).compare(x.substr(pos2, n2));
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR int compare(const charT* x) const {
|
||||
return compare(basic_string_view(x));
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1, const charT* x) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x));
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR int compare(size_type pos1, size_type n1,
|
||||
const charT* x, size_type n2) const {
|
||||
return substr(pos1, n1).compare(basic_string_view(x, n2));
|
||||
}
|
||||
|
||||
// Searches
|
||||
|
||||
BOOST_CONSTEXPR bool starts_with(charT c) const { // Boost extension
|
||||
return !empty() && traits::eq ( c, front());
|
||||
}
|
||||
BOOST_CONSTEXPR bool starts_with(basic_string_view x) const { // Boost extension
|
||||
return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
|
||||
}
|
||||
|
||||
BOOST_CONSTEXPR bool ends_with(charT c) const {
|
||||
return !empty() && traits::eq ( c, back()); // Boost extension
|
||||
}
|
||||
BOOST_CONSTEXPR bool ends_with(basic_string_view x) const { // Boost extension
|
||||
return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_,
|
||||
x.ptr_, x.len_ ) == 0;
|
||||
}
|
||||
|
||||
// find
|
||||
BOOST_CXX14_CONSTEXPR size_type find(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos > size())
|
||||
return npos;
|
||||
if (s.empty())
|
||||
return pos;
|
||||
const_iterator iter = std::search(this->cbegin() + pos, this->cend(),
|
||||
s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos, size_type n) const
|
||||
{ return find(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find(const charT* s, size_type pos = 0) const
|
||||
{ return find(basic_string_view(s), pos); }
|
||||
|
||||
// rfind
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (len_ < s.len_)
|
||||
return npos;
|
||||
if (pos > len_ - s.len_)
|
||||
pos = len_ - s.len_;
|
||||
if (s.len_ == 0u) // an empty string is always found
|
||||
return pos;
|
||||
for (const charT* cur = ptr_ + pos;; --cur) {
|
||||
if (traits::compare(cur, s.ptr_, s.len_) == 0)
|
||||
return cur - ptr_;
|
||||
if (cur == ptr_)
|
||||
return npos;
|
||||
};
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return rfind(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos, size_type n) const
|
||||
{ return rfind(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type rfind(const charT* s, size_type pos = npos) const
|
||||
{ return rfind(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_ || s.len_ == 0)
|
||||
return npos;
|
||||
const_iterator iter = std::find_first_of
|
||||
(this->cbegin () + pos, this->cend (), s.cbegin (), s.cend (), traits::eq);
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos, size_type n) const
|
||||
{ return find_first_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_of(const charT* s, size_type pos = 0) const
|
||||
{ return find_first_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (s.len_ == 0u)
|
||||
return npos;
|
||||
if (pos >= len_)
|
||||
pos = 0;
|
||||
else
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = std::find_first_of
|
||||
( this->crbegin () + pos, this->crend (), s.cbegin (), s.cend (), traits::eq );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos, size_type n) const
|
||||
{ return find_last_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_of(const charT* s, size_type pos = npos) const
|
||||
{ return find_last_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_first_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(basic_string_view s, size_type pos = 0) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
return npos;
|
||||
if (s.len_ == 0)
|
||||
return pos;
|
||||
const_iterator iter = find_not_of ( this->cbegin () + pos, this->cend (), s );
|
||||
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(charT c, size_type pos = 0) const BOOST_NOEXCEPT
|
||||
{ return find_first_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos, size_type n) const
|
||||
{ return find_first_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_first_not_of(const charT* s, size_type pos = 0) const
|
||||
{ return find_first_not_of(basic_string_view(s), pos); }
|
||||
|
||||
// find_last_not_of
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(basic_string_view s, size_type pos = npos) const BOOST_NOEXCEPT {
|
||||
if (pos >= len_)
|
||||
pos = len_ - 1;;
|
||||
if (s.len_ == 0u)
|
||||
return pos;
|
||||
pos = len_ - (pos+1);
|
||||
const_reverse_iterator iter = find_not_of ( this->crbegin () + pos, this->crend (), s );
|
||||
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
|
||||
}
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(charT c, size_type pos = npos) const BOOST_NOEXCEPT
|
||||
{ return find_last_not_of(basic_string_view(&c, 1), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos, size_type n) const
|
||||
{ return find_last_not_of(basic_string_view(s, n), pos); }
|
||||
BOOST_CXX14_CONSTEXPR size_type find_last_not_of(const charT* s, size_type pos = npos) const
|
||||
{ return find_last_not_of(basic_string_view(s), pos); }
|
||||
|
||||
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_view 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_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if ( x.size () != y.size ()) return false;
|
||||
return x.compare(y) == 0;
|
||||
}
|
||||
|
||||
// Inequality
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
if ( x.size () != y.size ()) return true;
|
||||
return x.compare(y) != 0;
|
||||
}
|
||||
|
||||
// Less than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) < 0;
|
||||
}
|
||||
|
||||
// Greater than
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) > 0;
|
||||
}
|
||||
|
||||
// Less than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) <= 0;
|
||||
}
|
||||
|
||||
// Greater than or equal to
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_view<charT, traits> x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return x.compare(y) >= 0;
|
||||
}
|
||||
|
||||
// "sufficient additional overloads of comparison functions"
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator==(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x == basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator==(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) == y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x != basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator!=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) != y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x < basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) < y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x > basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) > y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x <= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator<=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) <= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(basic_string_view<charT, traits> x,
|
||||
const std::basic_string<charT, traits, Allocator> & y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits, typename Allocator>
|
||||
inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<charT, traits>(x) >= y;
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(basic_string_view<charT, traits> x,
|
||||
const charT * y) BOOST_NOEXCEPT {
|
||||
return x >= basic_string_view<charT, traits>(y);
|
||||
}
|
||||
|
||||
template<typename charT, typename traits>
|
||||
inline bool operator>=(const charT * x,
|
||||
basic_string_view<charT, traits> y) BOOST_NOEXCEPT {
|
||||
return basic_string_view<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_view<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_view<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_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::string(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (string_view str, size_t* idx=0) {
|
||||
return std::stof ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (string_view str, size_t* idx=0) {
|
||||
return std::stod ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (string_view str, size_t* idx=0) {
|
||||
return std::stold ( std::string(str), idx );
|
||||
}
|
||||
|
||||
inline int stoi (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoi ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long stol (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stol ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoul ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline long long stoll (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoll ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) {
|
||||
return std::stoull ( std::wstring(str), idx, base );
|
||||
}
|
||||
|
||||
inline float stof (wstring_view str, size_t* idx=0) {
|
||||
return std::stof ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline double stod (wstring_view str, size_t* idx=0) {
|
||||
return std::stod ( std::wstring(str), idx );
|
||||
}
|
||||
|
||||
inline long double stold (wstring_view str, size_t* idx=0) {
|
||||
return std::stold ( std::wstring(str), idx );
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
namespace std {
|
||||
// Hashing
|
||||
template<> struct hash<boost::string_view>;
|
||||
template<> struct hash<boost::u16string_view>;
|
||||
template<> struct hash<boost::u32string_view>;
|
||||
template<> struct hash<boost::wstring_view>;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
39
include/boost/utility/string_view_fwd.hpp
Normal file
39
include/boost/utility/string_view_fwd.hpp
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
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
|
||||
Updated July 2015 to reflect the Library Fundamentals TS
|
||||
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4480.html
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BOOST_STRING_VIEW_FWD_HPP
|
||||
#define BOOST_STRING_VIEW_FWD_HPP
|
||||
|
||||
#include <boost/config.hpp>
|
||||
#include <string>
|
||||
|
||||
namespace boost {
|
||||
|
||||
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view;
|
||||
typedef basic_string_view<char, std::char_traits<char> > string_view;
|
||||
typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view;
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR16_T
|
||||
typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view;
|
||||
#endif
|
||||
|
||||
#ifndef BOOST_NO_CXX11_CHAR32_T
|
||||
typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -30,6 +30,10 @@ test-suite utility
|
||||
[ 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 string_view_test1.cpp unit_test_framework ]
|
||||
[ run string_view_test2.cpp unit_test_framework ]
|
||||
[ run string_view_test3.cpp ]
|
||||
[ run string_view_test_io.cpp unit_test_framework ]
|
||||
[ run ../value_init_test.cpp ]
|
||||
[ run ../value_init_workaround_test.cpp ]
|
||||
[ run ../initialized_test.cpp ]
|
||||
|
15
test/msvc/common.props
Normal file
15
test/msvc/common.props
Normal file
@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Label="PropertySheets" />
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>../../../../..</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<PostBuildEvent>
|
||||
<Command>"$(TargetDir)\$(TargetName).exe"</Command>
|
||||
</PostBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup />
|
||||
</Project>
|
22
test/msvc/string_view.sln
Normal file
22
test/msvc/string_view.sln
Normal file
@ -0,0 +1,22 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.22823.1
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "string_view_test3", "string_view_test3\string_view_test3.vcxproj", "{4921E3AB-4466-4592-BA7A-3460AD616956}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{4921E3AB-4466-4592-BA7A-3460AD616956}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{4921E3AB-4466-4592-BA7A-3460AD616956}.Debug|x86.Build.0 = Debug|Win32
|
||||
{4921E3AB-4466-4592-BA7A-3460AD616956}.Release|x86.ActiveCfg = Release|Win32
|
||||
{4921E3AB-4466-4592-BA7A-3460AD616956}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
EndGlobal
|
90
test/msvc/string_view_test3/string_view_test3.vcxproj
Normal file
90
test/msvc/string_view_test3/string_view_test3.vcxproj
Normal file
@ -0,0 +1,90 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{4921E3AB-4466-4592-BA7A-3460AD616956}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>string_view_test3</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v140</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\common.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="..\common.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\..\string_view_test3.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
113
test/string_view_test1.cpp
Normal file
113
test/string_view_test1.cpp
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef _SCL_SECURE_NO_WARNINGS
|
||||
# define _SCL_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
typedef boost::string_view string_view;
|
||||
|
||||
// Should be equal
|
||||
void interop ( const std::string &str, string_view 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_view sr1; // NULL, 0
|
||||
string_view sr2 ( NULL, 0 );
|
||||
string_view sr3 ( p, 0 );
|
||||
string_view 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_view 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_view 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++;
|
||||
}
|
||||
}
|
327
test/string_view_test2.cpp
Normal file
327
test/string_view_test2.cpp
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
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
|
||||
*/
|
||||
|
||||
#ifndef _SCL_SECURE_NO_WARNINGS
|
||||
# define _SCL_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <iostream>
|
||||
#include <cstring> // for std::strchr
|
||||
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#define BOOST_TEST_MAIN
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
typedef boost::string_view string_view;
|
||||
|
||||
void ends_with ( const char *arg ) {
|
||||
const size_t sz = std::strlen ( arg );
|
||||
string_view sr ( arg );
|
||||
string_view 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_view ()));
|
||||
}
|
||||
|
||||
void starts_with ( const char *arg ) {
|
||||
const size_t sz = std::strlen ( arg );
|
||||
string_view sr ( arg );
|
||||
string_view 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_view ()));
|
||||
}
|
||||
|
||||
void reverse ( const char *arg ) {
|
||||
// Round trip
|
||||
string_view sr1 ( arg );
|
||||
std::string string1 ( sr1.rbegin (), sr1.rend ());
|
||||
string_view 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_view::size_type ptr_diff ( const char *res, const char *base ) {
|
||||
BOOST_CHECK ( res >= base );
|
||||
return static_cast<string_view::size_type> ( res - base );
|
||||
}
|
||||
|
||||
void find ( const char *arg ) {
|
||||
string_view sr1;
|
||||
string_view sr2;
|
||||
const char *p;
|
||||
|
||||
// Look for each character in the string(searching from the start)
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( *p ) {
|
||||
string_view::size_type pos = sr1.find(*p);
|
||||
BOOST_CHECK ( pos != string_view::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_view::size_type pos = sr1.rfind(*p);
|
||||
BOOST_CHECK ( pos != string_view::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_view sr3 ( p, 2 );
|
||||
string_view::size_type pos = sr1.find ( sr3 );
|
||||
BOOST_CHECK ( pos != string_view::npos && pos <= static_cast<string_view::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 ( unsigned char ch = 1u; ; ++ch ) {
|
||||
string_view::size_type pos = sr1.find(ch);
|
||||
const char *strp = std::strchr ( arg, ch );
|
||||
BOOST_CHECK (( strp == NULL ) == ( pos == string_view::npos ));
|
||||
if ( strp != NULL )
|
||||
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
|
||||
if (ch == 255u)
|
||||
break;
|
||||
}
|
||||
|
||||
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 ( unsigned char ch = 1u; ; ++ch ) {
|
||||
string_view::size_type pos = sr1.rfind(ch);
|
||||
const char *strp = std::strrchr ( arg, ch );
|
||||
BOOST_CHECK (( strp == NULL ) == ( pos == string_view::npos ));
|
||||
if ( strp != NULL )
|
||||
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
|
||||
if (ch == 255u)
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
// Find everything at the start
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( !sr1.empty ()) {
|
||||
string_view::size_type pos = sr1.find(*p);
|
||||
BOOST_CHECK ( pos == 0 );
|
||||
sr1.remove_prefix (1);
|
||||
++p;
|
||||
}
|
||||
|
||||
// Find everything at the end
|
||||
sr1 = arg;
|
||||
p = arg + std::strlen ( arg ) - 1;
|
||||
while ( !sr1.empty ()) {
|
||||
string_view::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_view::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 + std::strlen ( arg ) - 1;
|
||||
while ( !sr1.empty ()) {
|
||||
string_view::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_view::npos );
|
||||
sr1.remove_prefix ( 1 );
|
||||
}
|
||||
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( *p ) {
|
||||
string_view::size_type pos1 = sr1.find_first_of(*p);
|
||||
string_view::size_type pos2 = sr1.find_first_not_of(*p);
|
||||
BOOST_CHECK ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
|
||||
if ( pos2 != string_view::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_view::npos );
|
||||
sr1.remove_suffix ( 1 );
|
||||
}
|
||||
|
||||
p = arg;
|
||||
sr1 = arg;
|
||||
while ( *p ) {
|
||||
string_view::size_type pos1 = sr1.find_last_of(*p);
|
||||
string_view::size_type pos2 = sr1.find_last_not_of(*p);
|
||||
BOOST_CHECK ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
|
||||
BOOST_CHECK ( pos2 == string_view::npos || pos1 < sr1.size ());
|
||||
if ( pos2 != string_view::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_view 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_view sr1;
|
||||
std::string str1;
|
||||
std::string str2 = str1;
|
||||
|
||||
str1.assign ( arg );
|
||||
sr1 = arg;
|
||||
BOOST_CHECK ( sr1 == sr1); // compare string_view and string_view
|
||||
BOOST_CHECK ( sr1 == str1); // compare string and string_view
|
||||
BOOST_CHECK ( str1 == sr1 ); // compare string_view and string
|
||||
BOOST_CHECK ( sr1 == arg ); // compare string_view and pointer
|
||||
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_view
|
||||
|
||||
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++;
|
||||
}
|
||||
}
|
482
test/string_view_test3.cpp
Normal file
482
test/string_view_test3.cpp
Normal file
@ -0,0 +1,482 @@
|
||||
/*
|
||||
<20> Copyright Beman Dawes 2015
|
||||
|
||||
Distributed under the Boost Software License, Version 1.0
|
||||
See http://www.boost.org/LICENSE_1_0.txt
|
||||
|
||||
For more information, see http://www.boost.org
|
||||
*/
|
||||
|
||||
#ifndef _SCL_SECURE_NO_WARNINGS
|
||||
# define _SCL_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
#include <boost/utility/string_view.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
|
||||
#define BOOST_LIGHTWEIGHT_TEST_OSTREAM std::cout
|
||||
#include <boost/core/lightweight_test.hpp>
|
||||
#include <boost/detail/lightweight_main.hpp>
|
||||
|
||||
namespace
|
||||
{
|
||||
void swap_test()
|
||||
{
|
||||
std::cout << "swap test..." << std::endl;
|
||||
|
||||
std::string s1("abcdefg");
|
||||
boost::string_view sv1(s1);
|
||||
std::string s2("xyz");
|
||||
boost::string_view sv2(s2);
|
||||
std::string s3;
|
||||
boost::string_view sv3(s3);
|
||||
|
||||
boost::string_view sv1_org(sv1);
|
||||
boost::string_view sv2_org(sv2);
|
||||
boost::string_view sv3_org(sv3);
|
||||
|
||||
sv1.swap(sv2);
|
||||
BOOST_TEST_EQ(sv1.data(), sv2_org.data());
|
||||
BOOST_TEST_EQ(sv2.data(), sv1_org.data());
|
||||
BOOST_TEST_EQ(sv1.size(), sv2_org.size());
|
||||
BOOST_TEST_EQ(sv2.size(), sv1_org.size());
|
||||
sv1.swap(sv2);
|
||||
BOOST_TEST_EQ(sv1.data(), sv1_org.data());
|
||||
BOOST_TEST_EQ(sv2.data(), sv2_org.data());
|
||||
BOOST_TEST_EQ(sv1.size(), sv1_org.size());
|
||||
BOOST_TEST_EQ(sv2.size(), sv2_org.size());
|
||||
|
||||
sv3.swap(sv1);
|
||||
BOOST_TEST_EQ(sv3.data(), sv1_org.data());
|
||||
BOOST_TEST_EQ(sv1.data(), sv3_org.data());
|
||||
BOOST_TEST_EQ(sv3.size(), sv1_org.size());
|
||||
BOOST_TEST_EQ(sv1.size(), sv3_org.size());
|
||||
sv3.swap(sv1);
|
||||
BOOST_TEST_EQ(sv1.data(), sv1_org.data());
|
||||
BOOST_TEST_EQ(sv3.data(), sv3_org.data());
|
||||
BOOST_TEST_EQ(sv1.size(), sv1_org.size());
|
||||
BOOST_TEST_EQ(sv3.size(), sv3_org.size());
|
||||
}
|
||||
|
||||
void copy_test()
|
||||
{
|
||||
std::cout << "copy test..." << std::endl;
|
||||
|
||||
std::string s1("abcdefg");
|
||||
boost::string_view sv1(s1);
|
||||
const std::size_t sz = 128u;
|
||||
char a[sz];
|
||||
|
||||
std::fill(a, a + sz, 'x');
|
||||
sv1.copy(a, sv1.size());
|
||||
BOOST_TEST(std::memcmp(sv1.data(), &a, sv1.size()) == 0);
|
||||
const char* p;
|
||||
for (p = a + sv1.size();
|
||||
p != a + sz && *p == 'x'; ++p) {}
|
||||
BOOST_TEST(p == a + sz);
|
||||
|
||||
std::fill(a, a + sz, 'x');
|
||||
sv1.copy(a, sv1.size()-2, 2);
|
||||
BOOST_TEST(std::memcmp(sv1.data()+2, &a, sv1.size()-2) == 0);
|
||||
for (p = a + sv1.size() - 2;
|
||||
p != a + sz && *p == 'x'; ++p) {}
|
||||
BOOST_TEST(p == a + sz);
|
||||
}
|
||||
|
||||
void compare_test()
|
||||
{
|
||||
std::cout << "compare test..." << std::endl;
|
||||
|
||||
}
|
||||
|
||||
void find_test()
|
||||
{
|
||||
std::cout << "find test..." << std::endl;
|
||||
|
||||
// find - test two modified and two new signatures
|
||||
std::string s1("ababcab");
|
||||
boost::string_view sv1(s1);
|
||||
std::string s2("abc");
|
||||
boost::string_view sv2(s2);
|
||||
std::string s3;
|
||||
boost::string_view sv3(s3);
|
||||
|
||||
// first signature
|
||||
BOOST_TEST_EQ(sv3.find(sv3), s3.find(s3)); // both strings empty
|
||||
BOOST_TEST_EQ(sv1.find(sv3), s1.find(s3)); // search string empty
|
||||
BOOST_TEST_EQ(sv3.find(sv2), s3.find(s2)); // searched string empty
|
||||
BOOST_TEST_EQ(sv1.find(sv3, sizeof(s1) + 2), s1.find(s3, sizeof(s1) + 2));
|
||||
BOOST_TEST_EQ(sv1.find(sv3, sizeof(s1) + 1), s1.find(s3, sizeof(s1) + 1));
|
||||
BOOST_TEST_EQ(sv1.find(sv3, sizeof(s1)), s1.find(s3, sizeof(s1)));
|
||||
BOOST_TEST_EQ(sv1.find(sv3, sizeof(s1)- 1), s1.find(s3, sizeof(s1)- 1));
|
||||
|
||||
BOOST_TEST_EQ(sv1.find(sv2), s1.find(s2));
|
||||
for (std::string::size_type i = 0; i <= sizeof(s1) + 1; ++i)
|
||||
{
|
||||
//std::cout << i << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find(sv2, i), s1.find(s2, i));
|
||||
}
|
||||
for (std::string::size_type i = 0; i <= sizeof(s1) + 1; ++i)
|
||||
{
|
||||
//std::cout << i << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find(sv3, i), s1.find(s3, i));
|
||||
}
|
||||
|
||||
// second signature
|
||||
for (std::string::size_type i = 0; i <= sizeof(s1) + 1; ++i)
|
||||
{
|
||||
//std::cout << i << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find('b', i), s1.find('b', i));
|
||||
}
|
||||
|
||||
// third signature
|
||||
for (std::string::size_type i = 0; i <= sizeof(s1) + 1; ++i)
|
||||
for (std::string::size_type j = 0; j <= 4; ++j)
|
||||
{
|
||||
//std::cout << i << " " << j << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find("abc", i, j), s1.find("abc", i, j));
|
||||
}
|
||||
|
||||
// fourth signature
|
||||
BOOST_TEST_EQ(sv1.find("abc"), s1.find("abc"));
|
||||
for (std::string::size_type i = 0; i <= sizeof(s1) + 1; ++i)
|
||||
BOOST_TEST_EQ(sv1.find("abc", i), s1.find("abc", i));
|
||||
}
|
||||
|
||||
void rfind_test()
|
||||
{
|
||||
std::cout << "rfind test..." << std::endl;
|
||||
|
||||
// rfind - test two modified and two new signatures
|
||||
std::string s1("ababcab");
|
||||
boost::string_view sv1(s1);
|
||||
std::string s2("ab");
|
||||
boost::string_view sv2(s2);
|
||||
std::string s3;
|
||||
boost::string_view sv3(s3);
|
||||
|
||||
// first signature
|
||||
BOOST_TEST_EQ(sv3.rfind(sv3), s3.rfind(s3)); // both strings empty
|
||||
BOOST_TEST_EQ(sv1.rfind(sv3), s1.rfind(s3)); // search string empty
|
||||
BOOST_TEST_EQ(sv3.rfind(sv2), s3.rfind(s2)); // searched string empty
|
||||
BOOST_TEST_EQ(sv1.find(sv3, s1.size() + 2), s1.find(s3, s1.size() + 2));
|
||||
BOOST_TEST_EQ(sv1.find(sv3, s1.size() + 1), s1.find(s3, s1.size() + 1));
|
||||
BOOST_TEST_EQ(sv1.rfind(sv3, s1.size()), s1.rfind(s3, s1.size()));
|
||||
BOOST_TEST_EQ(sv1.rfind(sv3, s1.size()- 1), s1.rfind(s3, s1.size()- 1));
|
||||
|
||||
BOOST_TEST_EQ(sv1.rfind(sv2), s1.rfind(s2));
|
||||
for (std::string::size_type i = s1.size(); i <= s1.size(); --i)
|
||||
{
|
||||
// std::cout << i << ": " << sv1.rfind(sv2, i) << " " << s1.rfind(s2, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.rfind(sv2, i), s1.rfind(s2, i));
|
||||
}
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << std::endl;
|
||||
BOOST_TEST_EQ(sv1.rfind(sv3, i), s1.rfind(s3, i));
|
||||
}
|
||||
|
||||
// second signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << std::endl;
|
||||
BOOST_TEST_EQ(sv1.rfind('b', i), s1.rfind('b', i));
|
||||
}
|
||||
|
||||
// third signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
for (std::string::size_type j = 0; j <= 4; ++j)
|
||||
{
|
||||
//std::cout << i << " " << j << std::endl;
|
||||
BOOST_TEST_EQ(sv1.rfind("abc", i, j), s1.rfind("abc", i, j));
|
||||
}
|
||||
|
||||
// fourth signature
|
||||
BOOST_TEST_EQ(sv1.rfind("abc"), s1.rfind("abc"));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
BOOST_TEST_EQ(sv1.rfind("abc", i), s1.rfind("abc", i));
|
||||
}
|
||||
|
||||
void find_first_of_test()
|
||||
{
|
||||
std::cout << "find_first_of test..." << std::endl;
|
||||
|
||||
// find_first_of - test two modified and two new signatures
|
||||
std::string s1("Hello World!");
|
||||
boost::string_view sv1(s1);
|
||||
std::string s2("o");
|
||||
boost::string_view sv2(s2);
|
||||
const char* s2c = "Good Bye";
|
||||
boost::string_view sv2c(s2c);
|
||||
std::string s3;
|
||||
boost::string_view sv3(s3);
|
||||
|
||||
// smoke test
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv2), s1.find_first_of(s2));
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv2, 5), s1.find_first_of(s2, 5));
|
||||
BOOST_TEST_EQ(sv1.find_first_of(s2c), s1.find_first_of(s2c));
|
||||
BOOST_TEST_EQ(sv1.find_first_of(s2c, 0, 4), s1.find_first_of(s2c, 0, 4));
|
||||
|
||||
// first signature
|
||||
BOOST_TEST_EQ(sv3.find_first_of(sv3), s3.find_first_of(s3)); // both strings empty
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv3), s1.find_first_of(s3)); // search string empty
|
||||
BOOST_TEST_EQ(sv3.find_first_of(sv2), s3.find_first_of(s2)); // searched string empty
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv3, s1.size() + 2), s1.find_first_of(s3, s1.size() + 2));
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv3, s1.size() + 1), s1.find_first_of(s3, s1.size() + 1));
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv3, s1.size()), s1.find_first_of(s3, s1.size()));
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv3, s1.size() - 1), s1.find_first_of(s3, s1.size() - 1));
|
||||
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv2), s1.find_first_of(s2));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_of(sv2, i) << " " << s1.find_first_of(s2, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv2, i), s1.find_first_of(s2, i));
|
||||
}
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_of(sv3, i) << " " << s1.find_first_of(s3, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_of(sv3, i), s1.find_first_of(s3, i));
|
||||
}
|
||||
|
||||
// second signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_of('o', i) << " " << s1.find_first_of('o', i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_of('o', i), s1.find_first_of('o', i));
|
||||
}
|
||||
|
||||
// third signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
for (std::string::size_type j = 0; j <= std::strlen(s2c) + 1; ++j)
|
||||
{
|
||||
//std::cout << i << "," << j << ": " << sv1.find_first_of(s2c, i, j) << " " << s1.find_first_of(s2c, i, j) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_of(s2c, i, j), s1.find_first_of(s2c, i, j));
|
||||
}
|
||||
|
||||
// fourth signature
|
||||
BOOST_TEST_EQ(sv1.find_first_of(s2c), s1.find_first_of(s2c));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_of(s2c, i) << " " << s1.find_first_of(s2c, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_of(s2c, i), s1.find_first_of(s2c, i));
|
||||
}
|
||||
}
|
||||
|
||||
void find_last_of_test()
|
||||
{
|
||||
std::cout << "find_last_of test..." << std::endl;
|
||||
|
||||
// find_last_of - test two modified and two new signatures
|
||||
std::string s1("Hello World!");
|
||||
boost::string_view sv1(s1);
|
||||
std::string s2("o");
|
||||
boost::string_view sv2(s2);
|
||||
const char* s2c = "Good Bye";
|
||||
boost::string_view sv2c(s2c);
|
||||
std::string s3;
|
||||
boost::string_view sv3(s3);
|
||||
|
||||
// smoke test
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv2), s1.find_last_of(s2));
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv2, 5), s1.find_last_of(s2, 5));
|
||||
BOOST_TEST_EQ(sv1.find_last_of(s2c), s1.find_last_of(s2c));
|
||||
BOOST_TEST_EQ(sv1.find_last_of(s2c, 0, 4), s1.find_last_of(s2c, 0, 4));
|
||||
|
||||
// first signature
|
||||
BOOST_TEST_EQ(sv3.find_last_of(sv3), s3.find_last_of(s3)); // both strings empty
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv3), s1.find_last_of(s3)); // search string empty
|
||||
BOOST_TEST_EQ(sv3.find_last_of(sv2), s3.find_last_of(s2)); // searched string empty
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv3, s1.size() + 2), s1.find_last_of(s3, s1.size() + 2));
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv3, s1.size() + 1), s1.find_last_of(s3, s1.size() + 1));
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv3, s1.size()), s1.find_last_of(s3, s1.size()));
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv3, s1.size() - 1), s1.find_last_of(s3, s1.size() - 1));
|
||||
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv2), s1.find_last_of(s2));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_of(sv2, i) << " " << s1.find_last_of(s2, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv2, i), s1.find_last_of(s2, i));
|
||||
}
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_of(sv3, i) << " " << s1.find_last_of(s3, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_of(sv3, i), s1.find_last_of(s3, i));
|
||||
}
|
||||
|
||||
// second signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_of('o', i) << " " << s1.find_last_of('o', i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_of('o', i), s1.find_last_of('o', i));
|
||||
}
|
||||
|
||||
// third signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
for (std::string::size_type j = 0; j <= std::strlen(s2c) + 1; ++j)
|
||||
{
|
||||
//std::cout << i << "," << j << ": " << sv1.find_last_of(s2c, i, j) << " " << s1.find_last_of(s2c, i, j) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_of(s2c, i, j), s1.find_last_of(s2c, i, j));
|
||||
}
|
||||
|
||||
// fourth signature
|
||||
BOOST_TEST_EQ(sv1.find_last_of(s2c), s1.find_last_of(s2c));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_of(s2c, i) << " " << s1.find_last_of(s2c, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_of(s2c, i), s1.find_last_of(s2c, i));
|
||||
}
|
||||
}
|
||||
|
||||
void find_first_not_of_test()
|
||||
{
|
||||
std::cout << "find_first_not_of test..." << std::endl;
|
||||
|
||||
// find_first_not_of - test two modified and two new signatures
|
||||
std::string s1("Hello World!");
|
||||
boost::string_view sv1(s1);
|
||||
std::string s2("o");
|
||||
boost::string_view sv2(s2);
|
||||
const char* s2c = "Good Bye";
|
||||
boost::string_view sv2c(s2c);
|
||||
std::string s3;
|
||||
boost::string_view sv3(s3);
|
||||
|
||||
// smoke test
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv2), s1.find_first_not_of(s2));
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv2, 5), s1.find_first_not_of(s2, 5));
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(s2c), s1.find_first_not_of(s2c));
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(s2c, 0, 4), s1.find_first_not_of(s2c, 0, 4));
|
||||
|
||||
// first signature
|
||||
BOOST_TEST_EQ(sv3.find_first_not_of(sv3), s3.find_first_not_of(s3)); // both strings empty
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv3), s1.find_first_not_of(s3)); // search string empty
|
||||
BOOST_TEST_EQ(sv3.find_first_not_of(sv2), s3.find_first_not_of(s2)); // searched string empty
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv3, s1.size() + 2), s1.find_first_not_of(s3, s1.size() + 2));
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv3, s1.size() + 1), s1.find_first_not_of(s3, s1.size() + 1));
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv3, s1.size()), s1.find_first_not_of(s3, s1.size()));
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv3, s1.size() - 1), s1.find_first_not_of(s3, s1.size() - 1));
|
||||
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv2), s1.find_first_not_of(s2));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_not_of(sv2, i) << " " << s1.find_first_not_of(s2, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv2, i), s1.find_first_not_of(s2, i));
|
||||
}
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_not_of(sv3, i) << " " << s1.find_first_not_of(s3, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(sv3, i), s1.find_first_not_of(s3, i));
|
||||
}
|
||||
|
||||
// second signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_not_of('o', i) << " " << s1.find_first_not_of('o', i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of('o', i), s1.find_first_not_of('o', i));
|
||||
}
|
||||
|
||||
// third signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
for (std::string::size_type j = 0; j <= std::strlen(s2c) + 1; ++j)
|
||||
{
|
||||
//std::cout << i << "," << j << ": " << sv1.find_first_not_of(s2c, i, j) << " " << s1.find_first_not_of(s2c, i, j) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(s2c, i, j), s1.find_first_not_of(s2c, i, j));
|
||||
}
|
||||
|
||||
// fourth signature
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(s2c), s1.find_first_not_of(s2c));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_first_not_of(s2c, i) << " " << s1.find_first_not_of(s2c, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_first_not_of(s2c, i), s1.find_first_not_of(s2c, i));
|
||||
}
|
||||
}
|
||||
|
||||
void find_last_not_of_test()
|
||||
{
|
||||
std::cout << "find_last_not_of test..." << std::endl;
|
||||
|
||||
// find_last_not_of - test two modified and two new signatures
|
||||
std::string s1("Hello World!");
|
||||
boost::string_view sv1(s1);
|
||||
std::string s2("o");
|
||||
boost::string_view sv2(s2);
|
||||
const char* s2c = "Good Bye";
|
||||
boost::string_view sv2c(s2c);
|
||||
std::string s3;
|
||||
boost::string_view sv3(s3);
|
||||
|
||||
// smoke test
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv2), s1.find_last_not_of(s2));
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv2, 5), s1.find_last_not_of(s2, 5));
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(s2c), s1.find_last_not_of(s2c));
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(s2c, 0, 4), s1.find_last_not_of(s2c, 0, 4));
|
||||
|
||||
// first signature
|
||||
BOOST_TEST_EQ(sv3.find_last_not_of(sv3), s3.find_last_not_of(s3)); // both strings empty
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv3), s1.find_last_not_of(s3)); // search string empty
|
||||
BOOST_TEST_EQ(sv3.find_last_not_of(sv2), s3.find_last_not_of(s2)); // searched string empty
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv3, s1.size() + 2), s1.find_last_not_of(s3, s1.size() + 2));
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv3, s1.size() + 1), s1.find_last_not_of(s3, s1.size() + 1));
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv3, s1.size()), s1.find_last_not_of(s3, s1.size()));
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv3, s1.size() - 1), s1.find_last_not_of(s3, s1.size() - 1));
|
||||
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv2), s1.find_last_not_of(s2));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_not_of(sv2, i) << " " << s1.find_last_not_of(s2, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv2, i), s1.find_last_not_of(s2, i));
|
||||
}
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_not_of(sv3, i) << " " << s1.find_last_not_of(s3, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(sv3, i), s1.find_last_not_of(s3, i));
|
||||
}
|
||||
|
||||
// second signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_not_of('o', i) << " " << s1.find_last_not_of('o', i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of('o', i), s1.find_last_not_of('o', i));
|
||||
}
|
||||
|
||||
// third signature
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
for (std::string::size_type j = 0; j <= std::strlen(s2c) + 1; ++j)
|
||||
{
|
||||
//std::cout << i << "," << j << ": " << sv1.find_last_not_of(s2c, i, j) << " " << s1.find_last_not_of(s2c, i, j) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(s2c, i, j), s1.find_last_not_of(s2c, i, j));
|
||||
}
|
||||
|
||||
// fourth signature
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(s2c), s1.find_last_not_of(s2c));
|
||||
for (std::string::size_type i = 0; i <= s1.size() + 1; ++i)
|
||||
{
|
||||
//std::cout << i << ": " << sv1.find_last_not_of(s2c, i) << " " << s1.find_last_not_of(s2c, i) << std::endl;
|
||||
BOOST_TEST_EQ(sv1.find_last_not_of(s2c, i), s1.find_last_not_of(s2c, i));
|
||||
}
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
int cpp_main(int argc, char* argv[])
|
||||
{
|
||||
// verify traits_type and const_pointer typedefs compile OK
|
||||
BOOST_TEST(boost::string_view::traits_type::eq('x', 'x'));
|
||||
BOOST_TEST_EQ(sizeof(boost::string_view::const_pointer), sizeof(&argc));
|
||||
|
||||
swap_test();
|
||||
copy_test();
|
||||
compare_test();
|
||||
find_test();
|
||||
rfind_test();
|
||||
find_first_of_test();
|
||||
find_last_of_test();
|
||||
find_first_not_of_test();
|
||||
find_last_not_of_test();
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
183
test/string_view_test_io.cpp
Normal file
183
test/string_view_test_io.cpp
Normal 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_view_test_io.cpp
|
||||
* \author Andrey Semashev
|
||||
* \date 26.05.2013
|
||||
*
|
||||
* \brief This header contains tests for stream operations of \c basic_string_view.
|
||||
*/
|
||||
|
||||
#define BOOST_TEST_MODULE string_view_test_io
|
||||
|
||||
#include <boost/utility/string_view.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_view 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_view_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_view< char_type > string_view_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
ostream_type strm;
|
||||
strm << string_view_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_view< char_type > string_view_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
// Test for padding
|
||||
{
|
||||
ostream_type strm_view;
|
||||
strm_view << ctx.begin << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_view.str() == strm_correct.str());
|
||||
}
|
||||
|
||||
// Test for long padding
|
||||
{
|
||||
ostream_type strm_view;
|
||||
strm_view << ctx.begin << std::setw(100) << string_view_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_view.str() == strm_correct.str());
|
||||
}
|
||||
|
||||
// Test that short width does not truncate the string
|
||||
{
|
||||
ostream_type strm_view;
|
||||
strm_view << ctx.begin << std::setw(1) << string_view_type(ctx.abcd) << ctx.end;
|
||||
|
||||
ostream_type strm_correct;
|
||||
strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
|
||||
|
||||
BOOST_CHECK(strm_view.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_view< char_type > string_view_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
ostream_type strm_view;
|
||||
strm_view << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_view_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_view.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_view< char_type > string_view_type;
|
||||
|
||||
context< char_type > ctx;
|
||||
|
||||
// Left alignment
|
||||
{
|
||||
ostream_type strm_view;
|
||||
strm_view << ctx.begin << std::left << std::setw(8) << string_view_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_view.str() == strm_correct.str());
|
||||
}
|
||||
|
||||
// Right alignment
|
||||
{
|
||||
ostream_type strm_view;
|
||||
strm_view << ctx.begin << std::right << std::setw(8) << string_view_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_view.str() == strm_correct.str());
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user