Globally change _ref to _view in file names and files. Add infrastructure for testing compliance with the TS. Add the first missing TS item, the basic_string_view typedef traits_type.

This commit is contained in:
Beman 2015-07-05 16:44:40 -04:00
parent 20b78d7667
commit 57d2173de9
10 changed files with 386 additions and 229 deletions

View File

@ -5,7 +5,7 @@
/ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) / file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
/] /]
[article String_Ref [article String_View
[quickbook 1.5] [quickbook 1.5]
[authors [Clow, Marshall]] [authors [Clow, Marshall]]
[copyright 2012 Marshall Clow] [copyright 2012 Marshall Clow]
@ -20,8 +20,8 @@
[section Overview] [section Overview]
[/===============] [/===============]
Boost.StringRef is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442: Boost.StringView is an implementation of Jeffrey Yaskin's [@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3442.html N3442:
string_ref: a non-owning reference to a string]. string_view: a non-owning reference to a string].
When you are parsing/processing strings from some external source, frequently you want to pass a piece of text to a procedure for specialized processing. The canonical way to do this is as a `std::string`, but that has certain drawbacks: 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:
@ -31,15 +31,15 @@ When you are parsing/processing strings from some external source, frequently yo
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. 3) A routine receives a constant `std::string` and wants to return a portion of the string, then it must create a new string to return.
`string_ref` is designed to solve these efficiency problems. A `string_ref` is a read-only reference to a contiguous sequence of characters, and provides much of the functionality of `std::string`. A `string_ref` is cheap to create, copy and pass by value, because it does not actually own the storage that it points to. `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_ref` is implemented as a small struct that contains a pointer to the start of the character data and a count. A `string_ref` is cheap to create and cheap to copy. 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_ref` acts as a container; it includes all the methods that you would expect in a container, including iteration support, `operator []`, `at` and `size`. It can be used with any of the iterator-based algorithms in the STL - as long as you don't need to change the underlying data (`sort` and `remove`, for example, will not work) `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_ref` provides a subset of the interface of `std::string`. This makes it easy to replace parameters of type `const std::string &` with `boost::string_ref`. Like `std::string`, `string_ref` has a static member variable named `npos` to denote the result of failed searches, and to mean "the end". 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_ref` does not own the data that it "points to", it introduces lifetime issues into code that uses it. The programmer must ensure that the data that a `string_ref` refers to exists as long as the `string_ref` does. 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.
[endsect] [endsect]
@ -48,7 +48,7 @@ Because a `string_ref` does not own the data that it "points to", it introduces
[section Examples] [section Examples]
[/===============] [/===============]
Integrating `string_ref` into your code is fairly simple. Wherever you pass a `const std::string &` or `std::string` as a parameter, that's a candidate for passing a `boost::string_ref`. 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 ) { std::string extract_part ( const std::string &bar ) {
return bar.substr ( 2, 3 ); return bar.substr ( 2, 3 );
@ -62,15 +62,15 @@ First, a temporary string is created from the string literal `"ABCDEFG"`, and it
Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data. Two `std::string`s are created, and two copy operations. That's (potentially) four memory allocations and deallocations, and the associated copying of data.
Now let's look at the same code with `string_ref`: Now let's look at the same code with `string_view`:
boost::string_ref extract_part ( boost::string_ref bar ) { boost::string_view extract_part ( boost::string_view bar ) {
return bar.substr ( 2, 3 ); return bar.substr ( 2, 3 );
} }
if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ } if ( extract_part ( "ABCDEFG" ).front() == "C" ) { /* do something */ }
No memory allocations. No copying of character data. No changes to the code other than the types. There are two `string_ref`s created, and two `string_ref`s copied, but those are cheap operations. 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] [endsect]
@ -79,21 +79,21 @@ No memory allocations. No copying of character data. No changes to the code othe
[section:reference Reference ] [section:reference Reference ]
[/=================] [/=================]
The header file "string_ref.hpp" defines a template `boost::basic_string_ref`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` . The header file "string_view.hpp" defines a template `boost::basic_string_view`, and four specializations - for `char` / `wchar_t` / `char16_t` / `char32_t` .
`#include <boost/utility/string_ref.hpp>` `#include <boost/utility/string_view.hpp>`
Construction and copying: Construction and copying:
BOOST_CONSTEXPR basic_string_ref (); // Constructs an empty string_ref BOOST_CONSTEXPR basic_string_view (); // Constructs an empty string_view
BOOST_CONSTEXPR basic_string_ref(const charT* str); // Constructs from a NULL-terminated string BOOST_CONSTEXPR basic_string_view(const charT* str); // Constructs from a NULL-terminated string
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len); // Constructs from a pointer, length pair BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len); // Constructs from a pointer, length pair
template<typename Allocator> template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string basic_string_view(const std::basic_string<charT, traits, Allocator>& str); // Constructs from a std::string
basic_string_ref (const basic_string_ref &rhs); basic_string_view (const basic_string_view &rhs);
basic_string_ref& operator=(const basic_string_ref &rhs); basic_string_view& operator=(const basic_string_view &rhs);
`string_ref` does not define a move constructor nor a move-assignment operator because copying a `string_ref` is just a cheap as moving one. `string_view` does not define a move constructor nor a move-assignment operator because copying a `string_view` is just a cheap as moving one.
Basic container-like functions: Basic container-like functions:
@ -120,7 +120,7 @@ Access to the individual elements (all of which are const):
BOOST_CONSTEXPR const charT& back() const ; BOOST_CONSTEXPR const charT& back() const ;
BOOST_CONSTEXPR const charT* data() const ; BOOST_CONSTEXPR const charT* data() const ;
Modifying the `string_ref` (but not the underlying data): Modifying the `string_view` (but not the underlying data):
void clear(); void clear();
void remove_prefix(size_type n); void remove_prefix(size_type n);
@ -128,27 +128,27 @@ Modifying the `string_ref` (but not the underlying data):
Searching: Searching:
size_type find(basic_string_ref s) const ; size_type find(basic_string_view s) const ;
size_type find(charT c) const ; size_type find(charT c) const ;
size_type rfind(basic_string_ref s) const ; size_type rfind(basic_string_view s) const ;
size_type rfind(charT c) const ; size_type rfind(charT c) const ;
size_type find_first_of(charT c) const ; size_type find_first_of(charT c) const ;
size_type find_last_of (charT c) const ; size_type find_last_of (charT c) const ;
size_type find_first_of(basic_string_ref s) const ; size_type find_first_of(basic_string_view s) const ;
size_type find_last_of(basic_string_ref s) const ; size_type find_last_of(basic_string_view s) const ;
size_type find_first_not_of(basic_string_ref s) const ; size_type find_first_not_of(basic_string_view s) const ;
size_type find_first_not_of(charT c) const ; size_type find_first_not_of(charT c) const ;
size_type find_last_not_of(basic_string_ref s) const ; size_type find_last_not_of(basic_string_view s) const ;
size_type find_last_not_of(charT c) const ; size_type find_last_not_of(charT c) const ;
String-like operations: String-like operations:
BOOST_CONSTEXPR basic_string_ref substr(size_type pos, size_type n=npos) const ; // Creates a new string_ref BOOST_CONSTEXPR basic_string_view substr(size_type pos, size_type n=npos) const ; // Creates a new string_view
bool starts_with(charT c) const ; bool starts_with(charT c) const ;
bool starts_with(basic_string_ref x) const ; bool starts_with(basic_string_view x) const ;
bool ends_with(charT c) const ; bool ends_with(charT c) const ;
bool ends_with(basic_string_ref x) const ; bool ends_with(basic_string_view x) const ;
[endsect] [endsect]

View File

@ -12,12 +12,12 @@
*/ */
#ifndef BOOST_STRING_REF_HPP #ifndef BOOST_STRING_VIEW_HPP
#define BOOST_STRING_REF_HPP #define BOOST_STRING_VIEW_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
#include <boost/detail/workaround.hpp> #include <boost/detail/workaround.hpp>
#include <boost/utility/string_ref_fwd.hpp> #include <boost/utility/string_view_fwd.hpp>
#include <boost/throw_exception.hpp> #include <boost/throw_exception.hpp>
#include <cstddef> #include <cstddef>
@ -32,22 +32,23 @@ namespace boost {
namespace detail { namespace detail {
// A helper functor because sometimes we don't have lambdas // A helper functor because sometimes we don't have lambdas
template <typename charT, typename traits> template <typename charT, typename traits>
class string_ref_traits_eq { class string_view_traits_eq {
public: public:
string_ref_traits_eq ( charT ch ) : ch_(ch) {} string_view_traits_eq ( charT ch ) : ch_(ch) {}
bool operator () ( charT val ) const { return traits::eq ( ch_, val ); } bool operator () ( charT val ) const { return traits::eq ( ch_, val ); }
charT ch_; charT ch_;
}; };
} }
template<typename charT, typename traits> template<typename charT, typename traits>
class basic_string_ref { class basic_string_view {
public: public:
// types // types
typedef traits traits_type;
typedef charT value_type; typedef charT value_type;
typedef const charT* pointer; typedef const charT* pointer;
typedef const charT& reference; typedef const charT& reference;
typedef const charT& const_reference; typedef const charT& const_viewerence;
typedef pointer const_iterator; // impl-defined typedef pointer const_iterator; // impl-defined
typedef const_iterator iterator; typedef const_iterator iterator;
typedef std::reverse_iterator<const_iterator> const_reverse_iterator; typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
@ -57,26 +58,26 @@ namespace boost {
static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1); static BOOST_CONSTEXPR_OR_CONST size_type npos = size_type(-1);
// construct/copy // construct/copy
BOOST_CONSTEXPR basic_string_ref () BOOST_CONSTEXPR basic_string_view ()
: ptr_(NULL), len_(0) {} : ptr_(NULL), len_(0) {}
BOOST_CONSTEXPR basic_string_ref (const basic_string_ref &rhs) BOOST_CONSTEXPR basic_string_view (const basic_string_view &rhs)
: ptr_(rhs.ptr_), len_(rhs.len_) {} : ptr_(rhs.ptr_), len_(rhs.len_) {}
basic_string_ref& operator=(const basic_string_ref &rhs) { basic_string_view& operator=(const basic_string_view &rhs) {
ptr_ = rhs.ptr_; ptr_ = rhs.ptr_;
len_ = rhs.len_; len_ = rhs.len_;
return *this; return *this;
} }
basic_string_ref(const charT* str) basic_string_view(const charT* str)
: ptr_(str), len_(traits::length(str)) {} : ptr_(str), len_(traits::length(str)) {}
template<typename Allocator> template<typename Allocator>
basic_string_ref(const std::basic_string<charT, traits, Allocator>& str) basic_string_view(const std::basic_string<charT, traits, Allocator>& str)
: ptr_(str.data()), len_(str.length()) {} : ptr_(str.data()), len_(str.length()) {}
BOOST_CONSTEXPR basic_string_ref(const charT* str, size_type len) BOOST_CONSTEXPR basic_string_view(const charT* str, size_type len)
: ptr_(str), len_(len) {} : ptr_(str), len_(len) {}
#ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
@ -111,7 +112,7 @@ namespace boost {
const charT& at(size_t pos) const { const charT& at(size_t pos) const {
if ( pos >= len_ ) if ( pos >= len_ )
BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_ref::at" ) ); BOOST_THROW_EXCEPTION( std::out_of_range ( "boost::string_view::at" ) );
return ptr_[pos]; return ptr_[pos];
} }
@ -135,31 +136,31 @@ namespace boost {
} }
// basic_string_ref string operations // basic_string_view string operations
basic_string_ref substr(size_type pos, size_type n=npos) const { basic_string_view substr(size_type pos, size_type n=npos) const {
if ( pos > size()) if ( pos > size())
BOOST_THROW_EXCEPTION( std::out_of_range ( "string_ref::substr" ) ); BOOST_THROW_EXCEPTION( std::out_of_range ( "string_view::substr" ) );
if ( n == npos || pos + n > size()) if ( n == npos || pos + n > size())
n = size () - pos; n = size () - pos;
return basic_string_ref ( data() + pos, n ); return basic_string_view ( data() + pos, n );
} }
int compare(basic_string_ref x) const { int compare(basic_string_view x) const {
const int cmp = traits::compare ( ptr_, x.ptr_, (std::min)(len_, x.len_)); 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 ); return cmp != 0 ? cmp : ( len_ == x.len_ ? 0 : len_ < x.len_ ? -1 : 1 );
} }
bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); } bool starts_with(charT c) const { return !empty() && traits::eq ( c, front()); }
bool starts_with(basic_string_ref x) const { bool starts_with(basic_string_view x) const {
return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0; return len_ >= x.len_ && traits::compare ( ptr_, x.ptr_, x.len_ ) == 0;
} }
bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); } bool ends_with(charT c) const { return !empty() && traits::eq ( c, back()); }
bool ends_with(basic_string_ref x) const { bool ends_with(basic_string_view x) const {
return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0; return len_ >= x.len_ && traits::compare ( ptr_ + len_ - x.len_, x.ptr_, x.len_ ) == 0;
} }
size_type find(basic_string_ref s) const { size_type find(basic_string_view s) const {
const_iterator iter = std::search ( this->cbegin (), this->cend (), const_iterator iter = std::search ( this->cbegin (), this->cend (),
s.cbegin (), s.cend (), traits::eq ); s.cbegin (), s.cend (), traits::eq );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
@ -167,11 +168,11 @@ namespace boost {
size_type find(charT c) const { size_type find(charT c) const {
const_iterator iter = std::find_if ( this->cbegin (), this->cend (), const_iterator iter = std::find_if ( this->cbegin (), this->cend (),
detail::string_ref_traits_eq<charT, traits> ( c )); detail::string_view_traits_eq<charT, traits> ( c ));
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
} }
size_type rfind(basic_string_ref s) const { size_type rfind(basic_string_view s) const {
const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (), const_reverse_iterator iter = std::search ( this->crbegin (), this->crend (),
s.crbegin (), s.crend (), traits::eq ); s.crbegin (), s.crend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
@ -179,26 +180,26 @@ namespace boost {
size_type rfind(charT c) const { size_type rfind(charT c) const {
const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (), const_reverse_iterator iter = std::find_if ( this->crbegin (), this->crend (),
detail::string_ref_traits_eq<charT, traits> ( c )); detail::string_view_traits_eq<charT, traits> ( c ));
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
} }
size_type find_first_of(charT c) const { return find (c); } size_type find_first_of(charT c) const { return find (c); }
size_type find_last_of (charT c) const { return rfind (c); } size_type find_last_of (charT c) const { return rfind (c); }
size_type find_first_of(basic_string_ref s) const { size_type find_first_of(basic_string_view s) const {
const_iterator iter = std::find_first_of const_iterator iter = std::find_first_of
( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq ); ( this->cbegin (), this->cend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
} }
size_type find_last_of(basic_string_ref s) const { size_type find_last_of(basic_string_view s) const {
const_reverse_iterator iter = std::find_first_of const_reverse_iterator iter = std::find_first_of
( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq ); ( this->crbegin (), this->crend (), s.cbegin (), s.cend (), traits::eq );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter); return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter);
} }
size_type find_first_not_of(basic_string_ref s) const { size_type find_first_not_of(basic_string_view s) const {
const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s ); const_iterator iter = find_not_of ( this->cbegin (), this->cend (), s );
return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter ); return iter == this->cend () ? npos : std::distance ( this->cbegin (), iter );
} }
@ -210,7 +211,7 @@ namespace boost {
return npos; return npos;
} }
size_type find_last_not_of(basic_string_ref s) const { size_type find_last_not_of(basic_string_view s) const {
const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s ); const_reverse_iterator iter = find_not_of ( this->crbegin (), this->crend (), s );
return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter ); return iter == this->crend () ? npos : reverse_distance ( this->crbegin (), iter );
} }
@ -229,7 +230,7 @@ namespace boost {
} }
template <typename Iterator> template <typename Iterator>
Iterator find_not_of ( Iterator first, Iterator last, basic_string_ref s ) const { Iterator find_not_of ( Iterator first, Iterator last, basic_string_view s ) const {
for ( ; first != last ; ++first ) for ( ; first != last ; ++first )
if ( 0 == traits::find ( s.ptr_, s.len_, *first )) if ( 0 == traits::find ( s.ptr_, s.len_, *first ))
return first; return first;
@ -246,160 +247,160 @@ namespace boost {
// Comparison operators // Comparison operators
// Equality // Equality
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator==(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) { inline bool operator==(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) {
if ( x.size () != y.size ()) return false; if ( x.size () != y.size ()) return false;
return x.compare(y) == 0; return x.compare(y) == 0;
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator==(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) { inline bool operator==(basic_string_view<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x == basic_string_ref<charT, traits>(y); return x == basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator==(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) { inline bool operator==(const std::basic_string<charT, traits, Allocator> & x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) == y; return basic_string_view<charT, traits>(x) == y;
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator==(basic_string_ref<charT, traits> x, const charT * y) { inline bool operator==(basic_string_view<charT, traits> x, const charT * y) {
return x == basic_string_ref<charT, traits>(y); return x == basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator==(const charT * x, basic_string_ref<charT, traits> y) { inline bool operator==(const charT * x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) == y; return basic_string_view<charT, traits>(x) == y;
} }
// Inequality // Inequality
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator!=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) { inline bool operator!=(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) {
if ( x.size () != y.size ()) return true; if ( x.size () != y.size ()) return true;
return x.compare(y) != 0; return x.compare(y) != 0;
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator!=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) { inline bool operator!=(basic_string_view<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x != basic_string_ref<charT, traits>(y); return x != basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) { inline bool operator!=(const std::basic_string<charT, traits, Allocator> & x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) != y; return basic_string_view<charT, traits>(x) != y;
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator!=(basic_string_ref<charT, traits> x, const charT * y) { inline bool operator!=(basic_string_view<charT, traits> x, const charT * y) {
return x != basic_string_ref<charT, traits>(y); return x != basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator!=(const charT * x, basic_string_ref<charT, traits> y) { inline bool operator!=(const charT * x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) != y; return basic_string_view<charT, traits>(x) != y;
} }
// Less than // Less than
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator<(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) { inline bool operator<(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) {
return x.compare(y) < 0; return x.compare(y) < 0;
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator<(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) { inline bool operator<(basic_string_view<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x < basic_string_ref<charT, traits>(y); return x < basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator<(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) { inline bool operator<(const std::basic_string<charT, traits, Allocator> & x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) < y; return basic_string_view<charT, traits>(x) < y;
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator<(basic_string_ref<charT, traits> x, const charT * y) { inline bool operator<(basic_string_view<charT, traits> x, const charT * y) {
return x < basic_string_ref<charT, traits>(y); return x < basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator<(const charT * x, basic_string_ref<charT, traits> y) { inline bool operator<(const charT * x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) < y; return basic_string_view<charT, traits>(x) < y;
} }
// Greater than // Greater than
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator>(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) { inline bool operator>(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) {
return x.compare(y) > 0; return x.compare(y) > 0;
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator>(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) { inline bool operator>(basic_string_view<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x > basic_string_ref<charT, traits>(y); return x > basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator>(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) { inline bool operator>(const std::basic_string<charT, traits, Allocator> & x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) > y; return basic_string_view<charT, traits>(x) > y;
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator>(basic_string_ref<charT, traits> x, const charT * y) { inline bool operator>(basic_string_view<charT, traits> x, const charT * y) {
return x > basic_string_ref<charT, traits>(y); return x > basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator>(const charT * x, basic_string_ref<charT, traits> y) { inline bool operator>(const charT * x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) > y; return basic_string_view<charT, traits>(x) > y;
} }
// Less than or equal to // Less than or equal to
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator<=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) { inline bool operator<=(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) {
return x.compare(y) <= 0; return x.compare(y) <= 0;
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator<=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) { inline bool operator<=(basic_string_view<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x <= basic_string_ref<charT, traits>(y); return x <= basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) { inline bool operator<=(const std::basic_string<charT, traits, Allocator> & x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) <= y; return basic_string_view<charT, traits>(x) <= y;
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator<=(basic_string_ref<charT, traits> x, const charT * y) { inline bool operator<=(basic_string_view<charT, traits> x, const charT * y) {
return x <= basic_string_ref<charT, traits>(y); return x <= basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator<=(const charT * x, basic_string_ref<charT, traits> y) { inline bool operator<=(const charT * x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) <= y; return basic_string_view<charT, traits>(x) <= y;
} }
// Greater than or equal to // Greater than or equal to
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator>=(basic_string_ref<charT, traits> x, basic_string_ref<charT, traits> y) { inline bool operator>=(basic_string_view<charT, traits> x, basic_string_view<charT, traits> y) {
return x.compare(y) >= 0; return x.compare(y) >= 0;
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator>=(basic_string_ref<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) { inline bool operator>=(basic_string_view<charT, traits> x, const std::basic_string<charT, traits, Allocator> & y) {
return x >= basic_string_ref<charT, traits>(y); return x >= basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits, typename Allocator> template<typename charT, typename traits, typename Allocator>
inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x, basic_string_ref<charT, traits> y) { inline bool operator>=(const std::basic_string<charT, traits, Allocator> & x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) >= y; return basic_string_view<charT, traits>(x) >= y;
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator>=(basic_string_ref<charT, traits> x, const charT * y) { inline bool operator>=(basic_string_view<charT, traits> x, const charT * y) {
return x >= basic_string_ref<charT, traits>(y); return x >= basic_string_view<charT, traits>(y);
} }
template<typename charT, typename traits> template<typename charT, typename traits>
inline bool operator>=(const charT * x, basic_string_ref<charT, traits> y) { inline bool operator>=(const charT * x, basic_string_view<charT, traits> y) {
return basic_string_ref<charT, traits>(x) >= y; return basic_string_view<charT, traits>(x) >= y;
} }
namespace detail { namespace detail {
@ -416,7 +417,7 @@ namespace boost {
} }
template<class charT, class traits> template<class charT, class traits>
void insert_aligned(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) { 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 size = str.size();
const std::size_t alignment_size = static_cast< std::size_t >(os.width()) - 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; const bool align_left = (os.flags() & std::basic_ostream<charT, traits>::adjustfield) == std::basic_ostream<charT, traits>::left;
@ -437,7 +438,7 @@ namespace boost {
// Inserter // Inserter
template<class charT, class traits> template<class charT, class traits>
inline std::basic_ostream<charT, traits>& inline std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const basic_string_ref<charT,traits>& str) { operator<<(std::basic_ostream<charT, traits>& os, const basic_string_view<charT,traits>& str) {
if (os.good()) { if (os.good()) {
const std::size_t size = str.size(); const std::size_t size = str.size();
const std::size_t w = static_cast< std::size_t >(os.width()); const std::size_t w = static_cast< std::size_t >(os.width());
@ -456,67 +457,67 @@ namespace boost {
// These are short-term implementations. // These are short-term implementations.
// In a production environment, I would rather avoid the copying. // In a production environment, I would rather avoid the copying.
// //
inline int stoi (string_ref str, size_t* idx=0, int base=10) { inline int stoi (string_view str, size_t* idx=0, int base=10) {
return std::stoi ( std::string(str), idx, base ); return std::stoi ( std::string(str), idx, base );
} }
inline long stol (string_ref str, size_t* idx=0, int base=10) { inline long stol (string_view str, size_t* idx=0, int base=10) {
return std::stol ( std::string(str), idx, base ); return std::stol ( std::string(str), idx, base );
} }
inline unsigned long stoul (string_ref str, size_t* idx=0, int base=10) { inline unsigned long stoul (string_view str, size_t* idx=0, int base=10) {
return std::stoul ( std::string(str), idx, base ); return std::stoul ( std::string(str), idx, base );
} }
inline long long stoll (string_ref str, size_t* idx=0, int base=10) { inline long long stoll (string_view str, size_t* idx=0, int base=10) {
return std::stoll ( std::string(str), idx, base ); return std::stoll ( std::string(str), idx, base );
} }
inline unsigned long long stoull (string_ref str, size_t* idx=0, int base=10) { inline unsigned long long stoull (string_view str, size_t* idx=0, int base=10) {
return std::stoull ( std::string(str), idx, base ); return std::stoull ( std::string(str), idx, base );
} }
inline float stof (string_ref str, size_t* idx=0) { inline float stof (string_view str, size_t* idx=0) {
return std::stof ( std::string(str), idx ); return std::stof ( std::string(str), idx );
} }
inline double stod (string_ref str, size_t* idx=0) { inline double stod (string_view str, size_t* idx=0) {
return std::stod ( std::string(str), idx ); return std::stod ( std::string(str), idx );
} }
inline long double stold (string_ref str, size_t* idx=0) { inline long double stold (string_view str, size_t* idx=0) {
return std::stold ( std::string(str), idx ); return std::stold ( std::string(str), idx );
} }
inline int stoi (wstring_ref str, size_t* idx=0, int base=10) { inline int stoi (wstring_view str, size_t* idx=0, int base=10) {
return std::stoi ( std::wstring(str), idx, base ); return std::stoi ( std::wstring(str), idx, base );
} }
inline long stol (wstring_ref str, size_t* idx=0, int base=10) { inline long stol (wstring_view str, size_t* idx=0, int base=10) {
return std::stol ( std::wstring(str), idx, base ); return std::stol ( std::wstring(str), idx, base );
} }
inline unsigned long stoul (wstring_ref str, size_t* idx=0, int base=10) { inline unsigned long stoul (wstring_view str, size_t* idx=0, int base=10) {
return std::stoul ( std::wstring(str), idx, base ); return std::stoul ( std::wstring(str), idx, base );
} }
inline long long stoll (wstring_ref str, size_t* idx=0, int base=10) { inline long long stoll (wstring_view str, size_t* idx=0, int base=10) {
return std::stoll ( std::wstring(str), idx, base ); return std::stoll ( std::wstring(str), idx, base );
} }
inline unsigned long long stoull (wstring_ref str, size_t* idx=0, int base=10) { inline unsigned long long stoull (wstring_view str, size_t* idx=0, int base=10) {
return std::stoull ( std::wstring(str), idx, base ); return std::stoull ( std::wstring(str), idx, base );
} }
inline float stof (wstring_ref str, size_t* idx=0) { inline float stof (wstring_view str, size_t* idx=0) {
return std::stof ( std::wstring(str), idx ); return std::stof ( std::wstring(str), idx );
} }
inline double stod (wstring_ref str, size_t* idx=0) { inline double stod (wstring_view str, size_t* idx=0) {
return std::stod ( std::wstring(str), idx ); return std::stod ( std::wstring(str), idx );
} }
inline long double stold (wstring_ref str, size_t* idx=0) { inline long double stold (wstring_view str, size_t* idx=0) {
return std::stold ( std::wstring(str), idx ); return std::stold ( std::wstring(str), idx );
} }
#endif #endif
@ -526,10 +527,10 @@ namespace boost {
#if 0 #if 0
namespace std { namespace std {
// Hashing // Hashing
template<> struct hash<boost::string_ref>; template<> struct hash<boost::string_view>;
template<> struct hash<boost::u16string_ref>; template<> struct hash<boost::u16string_view>;
template<> struct hash<boost::u32string_ref>; template<> struct hash<boost::u32string_view>;
template<> struct hash<boost::wstring_ref>; template<> struct hash<boost::wstring_view>;
} }
#endif #endif

View File

@ -12,24 +12,24 @@
*/ */
#ifndef BOOST_STRING_REF_FWD_HPP #ifndef BOOST_STRING_VIEW_FWD_HPP
#define BOOST_STRING_REF_FWD_HPP #define BOOST_STRING_VIEW_FWD_HPP
#include <boost/config.hpp> #include <boost/config.hpp>
#include <string> #include <string>
namespace boost { namespace boost {
template<typename charT, typename traits = std::char_traits<charT> > class basic_string_ref; template<typename charT, typename traits = std::char_traits<charT> > class basic_string_view;
typedef basic_string_ref<char, std::char_traits<char> > string_ref; typedef basic_string_view<char, std::char_traits<char> > string_view;
typedef basic_string_ref<wchar_t, std::char_traits<wchar_t> > wstring_ref; typedef basic_string_view<wchar_t, std::char_traits<wchar_t> > wstring_view;
#ifndef BOOST_NO_CXX11_CHAR16_T #ifndef BOOST_NO_CXX11_CHAR16_T
typedef basic_string_ref<char16_t, std::char_traits<char16_t> > u16string_ref; typedef basic_string_view<char16_t, std::char_traits<char16_t> > u16string_view;
#endif #endif
#ifndef BOOST_NO_CXX11_CHAR32_T #ifndef BOOST_NO_CXX11_CHAR32_T
typedef basic_string_ref<char32_t, std::char_traits<char32_t> > u32string_ref; typedef basic_string_view<char32_t, std::char_traits<char32_t> > u32string_view;
#endif #endif
} }

15
test/msvc/common.props Normal file
View 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
View 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

View 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>

View File

@ -11,15 +11,15 @@
#include <algorithm> #include <algorithm>
#include <string> #include <string>
#include <boost/utility/string_ref.hpp> #include <boost/utility/string_view.hpp>
#define BOOST_TEST_MAIN #define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
typedef boost::string_ref string_ref; typedef boost::string_view string_view;
// Should be equal // Should be equal
void interop ( const std::string &str, string_ref ref ) { void interop ( const std::string &str, string_view ref ) {
// BOOST_CHECK ( str == ref ); // BOOST_CHECK ( str == ref );
BOOST_CHECK ( str.size () == ref.size ()); BOOST_CHECK ( str.size () == ref.size ());
BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ())); BOOST_CHECK ( std::equal ( str.begin (), str.end (), ref.begin ()));
@ -28,10 +28,10 @@ void interop ( const std::string &str, string_ref ref ) {
void null_tests ( const char *p ) { void null_tests ( const char *p ) {
// All zero-length string-refs should be equal // All zero-length string-refs should be equal
string_ref sr1; // NULL, 0 string_view sr1; // NULL, 0
string_ref sr2 ( NULL, 0 ); string_view sr2 ( NULL, 0 );
string_ref sr3 ( p, 0 ); string_view sr3 ( p, 0 );
string_ref sr4 ( p ); string_view sr4 ( p );
sr4.clear (); sr4.clear ();
BOOST_CHECK ( sr1 == sr2 ); BOOST_CHECK ( sr1 == sr2 );
@ -43,7 +43,7 @@ void null_tests ( const char *p ) {
// make sure that substrings work just like strings // make sure that substrings work just like strings
void test_substr ( const std::string &str ) { void test_substr ( const std::string &str ) {
const size_t sz = str.size (); const size_t sz = str.size ();
string_ref ref ( str ); string_view ref ( str );
// Substrings at the end // Substrings at the end
for ( size_t i = 0; i <= sz; ++ i ) for ( size_t i = 0; i <= sz; ++ i )
@ -63,7 +63,7 @@ void test_substr ( const std::string &str ) {
void test_remove ( const std::string &str ) { void test_remove ( const std::string &str ) {
const size_t sz = str.size (); const size_t sz = str.size ();
std::string work; std::string work;
string_ref ref; string_view ref;
for ( size_t i = 1; i <= sz; ++i ) { for ( size_t i = 1; i <= sz; ++i ) {
work = str; work = str;

View File

@ -10,17 +10,17 @@
#include <iostream> #include <iostream>
#include <cstring> // for std::strchr #include <cstring> // for std::strchr
#include <boost/utility/string_ref.hpp> #include <boost/utility/string_view.hpp>
#define BOOST_TEST_MAIN #define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp> #include <boost/test/unit_test.hpp>
typedef boost::string_ref string_ref; typedef boost::string_view string_view;
void ends_with ( const char *arg ) { void ends_with ( const char *arg ) {
const size_t sz = std::strlen ( arg ); const size_t sz = std::strlen ( arg );
string_ref sr ( arg ); string_view sr ( arg );
string_ref sr2 ( arg ); string_view sr2 ( arg );
const char *p = arg; const char *p = arg;
while ( *p ) { while ( *p ) {
@ -44,13 +44,13 @@ void ends_with ( const char *arg ) {
if ( sz > 0 ) if ( sz > 0 )
BOOST_CHECK ( sr2.ends_with ( ch )); BOOST_CHECK ( sr2.ends_with ( ch ));
BOOST_CHECK ( !sr2.ends_with ( ++ch )); BOOST_CHECK ( !sr2.ends_with ( ++ch ));
BOOST_CHECK ( sr2.ends_with ( string_ref ())); BOOST_CHECK ( sr2.ends_with ( string_view ()));
} }
void starts_with ( const char *arg ) { void starts_with ( const char *arg ) {
const size_t sz = std::strlen ( arg ); const size_t sz = std::strlen ( arg );
string_ref sr ( arg ); string_view sr ( arg );
string_ref sr2 ( arg ); string_view sr2 ( arg );
const char *p = arg + std::strlen ( arg ) - 1; const char *p = arg + std::strlen ( arg ) - 1;
while ( p >= arg ) { while ( p >= arg ) {
std::string foo ( arg, p + 1 ); std::string foo ( arg, p + 1 );
@ -68,14 +68,14 @@ void starts_with ( const char *arg ) {
if ( sz > 0 ) if ( sz > 0 )
BOOST_CHECK ( sr2.starts_with ( ch )); BOOST_CHECK ( sr2.starts_with ( ch ));
BOOST_CHECK ( !sr2.starts_with ( ++ch )); BOOST_CHECK ( !sr2.starts_with ( ++ch ));
BOOST_CHECK ( sr2.starts_with ( string_ref ())); BOOST_CHECK ( sr2.starts_with ( string_view ()));
} }
void reverse ( const char *arg ) { void reverse ( const char *arg ) {
// Round trip // Round trip
string_ref sr1 ( arg ); string_view sr1 ( arg );
std::string string1 ( sr1.rbegin (), sr1.rend ()); std::string string1 ( sr1.rbegin (), sr1.rend ());
string_ref sr2 ( string1 ); string_view sr2 ( string1 );
std::string string2 ( sr2.rbegin (), sr2.rend ()); std::string string2 ( sr2.rbegin (), sr2.rend ());
BOOST_CHECK ( std::equal ( sr2.rbegin (), sr2.rend (), arg )); BOOST_CHECK ( std::equal ( sr2.rbegin (), sr2.rend (), arg ));
@ -84,22 +84,22 @@ void reverse ( const char *arg ) {
} }
// This helper function eliminates signed vs. unsigned warnings // This helper function eliminates signed vs. unsigned warnings
string_ref::size_type ptr_diff ( const char *res, const char *base ) { string_view::size_type ptr_diff ( const char *res, const char *base ) {
BOOST_CHECK ( res >= base ); BOOST_CHECK ( res >= base );
return static_cast<string_ref::size_type> ( res - base ); return static_cast<string_view::size_type> ( res - base );
} }
void find ( const char *arg ) { void find ( const char *arg ) {
string_ref sr1; string_view sr1;
string_ref sr2; string_view sr2;
const char *p; const char *p;
// Look for each character in the string(searching from the start) // Look for each character in the string(searching from the start)
p = arg; p = arg;
sr1 = arg; sr1 = arg;
while ( *p ) { while ( *p ) {
string_ref::size_type pos = sr1.find(*p); string_view::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos != string_ref::npos && ( pos <= ptr_diff ( p, arg ))); BOOST_CHECK ( pos != string_view::npos && ( pos <= ptr_diff ( p, arg )));
++p; ++p;
} }
@ -107,8 +107,8 @@ void find ( const char *arg ) {
p = arg; p = arg;
sr1 = arg; sr1 = arg;
while ( *p ) { while ( *p ) {
string_ref::size_type pos = sr1.rfind(*p); string_view::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos != string_ref::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg ))); BOOST_CHECK ( pos != string_view::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
++p; ++p;
} }
@ -116,9 +116,9 @@ void find ( const char *arg ) {
sr1 = arg; sr1 = arg;
p = arg; p = arg;
while ( *p && *(p+1)) { while ( *p && *(p+1)) {
string_ref sr3 ( p, 2 ); string_view sr3 ( p, 2 );
string_ref::size_type pos = sr1.find ( sr3 ); string_view::size_type pos = sr1.find ( sr3 );
BOOST_CHECK ( pos != string_ref::npos && pos <= static_cast<string_ref::size_type>( p - arg )); BOOST_CHECK ( pos != string_view::npos && pos <= static_cast<string_view::size_type>( p - arg ));
p++; p++;
} }
@ -127,9 +127,9 @@ void find ( const char *arg ) {
// for all possible chars, see if we find them in the right place. // 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 // Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) { for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.find(ch); string_view::size_type pos = sr1.find(ch);
const char *strp = std::strchr ( arg, ch ); const char *strp = std::strchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos )); BOOST_CHECK (( strp == NULL ) == ( pos == string_view::npos ));
if ( strp != NULL ) if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos ); BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
} }
@ -139,9 +139,9 @@ void find ( const char *arg ) {
// for all possible chars, see if we find them in the right place. // 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 // Note that strchr will/might do the _wrong_ thing if we search for NULL
for ( int ch = 1; ch < 256; ++ch ) { for ( int ch = 1; ch < 256; ++ch ) {
string_ref::size_type pos = sr1.rfind(ch); string_view::size_type pos = sr1.rfind(ch);
const char *strp = std::strrchr ( arg, ch ); const char *strp = std::strrchr ( arg, ch );
BOOST_CHECK (( strp == NULL ) == ( pos == string_ref::npos )); BOOST_CHECK (( strp == NULL ) == ( pos == string_view::npos ));
if ( strp != NULL ) if ( strp != NULL )
BOOST_CHECK ( ptr_diff ( strp, arg ) == pos ); BOOST_CHECK ( ptr_diff ( strp, arg ) == pos );
} }
@ -151,7 +151,7 @@ void find ( const char *arg ) {
p = arg; p = arg;
sr1 = arg; sr1 = arg;
while ( !sr1.empty ()) { while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find(*p); string_view::size_type pos = sr1.find(*p);
BOOST_CHECK ( pos == 0 ); BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1); sr1.remove_prefix (1);
++p; ++p;
@ -161,7 +161,7 @@ void find ( const char *arg ) {
sr1 = arg; sr1 = arg;
p = arg + std::strlen ( arg ) - 1; p = arg + std::strlen ( arg ) - 1;
while ( !sr1.empty ()) { while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.rfind(*p); string_view::size_type pos = sr1.rfind(*p);
BOOST_CHECK ( pos == sr1.size () - 1 ); BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1); sr1.remove_suffix (1);
--p; --p;
@ -171,7 +171,7 @@ void find ( const char *arg ) {
sr1 = arg; sr1 = arg;
p = arg; p = arg;
while ( !sr1.empty ()) { while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find_first_of(*p); string_view::size_type pos = sr1.find_first_of(*p);
BOOST_CHECK ( pos == 0 ); BOOST_CHECK ( pos == 0 );
sr1.remove_prefix (1); sr1.remove_prefix (1);
++p; ++p;
@ -182,7 +182,7 @@ void find ( const char *arg ) {
sr1 = arg; sr1 = arg;
p = arg + std::strlen ( arg ) - 1; p = arg + std::strlen ( arg ) - 1;
while ( !sr1.empty ()) { while ( !sr1.empty ()) {
string_ref::size_type pos = sr1.find_last_of(*p); string_view::size_type pos = sr1.find_last_of(*p);
BOOST_CHECK ( pos == sr1.size () - 1 ); BOOST_CHECK ( pos == sr1.size () - 1 );
sr1.remove_suffix (1); sr1.remove_suffix (1);
--p; --p;
@ -193,17 +193,17 @@ void find ( const char *arg ) {
sr2 = arg; sr2 = arg;
while ( !sr1.empty() ) { while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 ); BOOST_CHECK ( sr1.find_first_of ( sr2 ) == 0 );
BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_ref::npos ); BOOST_CHECK ( sr1.find_first_not_of ( sr2 ) == string_view::npos );
sr1.remove_prefix ( 1 ); sr1.remove_prefix ( 1 );
} }
p = arg; p = arg;
sr1 = arg; sr1 = arg;
while ( *p ) { while ( *p ) {
string_ref::size_type pos1 = sr1.find_first_of(*p); string_view::size_type pos1 = sr1.find_first_of(*p);
string_ref::size_type pos2 = sr1.find_first_not_of(*p); string_view::size_type pos2 = sr1.find_first_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg )); BOOST_CHECK ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 <= ptr_diff ( p, arg ));
if ( pos2 != string_ref::npos ) { if ( pos2 != string_view::npos ) {
for ( size_t i = 0 ; i < pos2; ++i ) for ( size_t i = 0 ; i < pos2; ++i )
BOOST_CHECK ( sr1[i] == *p ); BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p ); BOOST_CHECK ( sr1 [ pos2 ] != *p );
@ -218,18 +218,18 @@ void find ( const char *arg ) {
sr2 = arg; sr2 = arg;
while ( !sr1.empty() ) { while ( !sr1.empty() ) {
BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 )); BOOST_CHECK ( sr1.find_last_of ( sr2 ) == ( sr1.size () - 1 ));
BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_ref::npos ); BOOST_CHECK ( sr1.find_last_not_of ( sr2 ) == string_view::npos );
sr1.remove_suffix ( 1 ); sr1.remove_suffix ( 1 );
} }
p = arg; p = arg;
sr1 = arg; sr1 = arg;
while ( *p ) { while ( *p ) {
string_ref::size_type pos1 = sr1.find_last_of(*p); string_view::size_type pos1 = sr1.find_last_of(*p);
string_ref::size_type pos2 = sr1.find_last_not_of(*p); string_view::size_type pos2 = sr1.find_last_not_of(*p);
BOOST_CHECK ( pos1 != string_ref::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg )); BOOST_CHECK ( pos1 != string_view::npos && pos1 < sr1.size () && pos1 >= ptr_diff ( p, arg ));
BOOST_CHECK ( pos2 == string_ref::npos || pos1 < sr1.size ()); BOOST_CHECK ( pos2 == string_view::npos || pos1 < sr1.size ());
if ( pos2 != string_ref::npos ) { if ( pos2 != string_view::npos ) {
for ( size_t i = sr1.size () -1 ; i > pos2; --i ) for ( size_t i = sr1.size () -1 ; i > pos2; --i )
BOOST_CHECK ( sr1[i] == *p ); BOOST_CHECK ( sr1[i] == *p );
BOOST_CHECK ( sr1 [ pos2 ] != *p ); BOOST_CHECK ( sr1 [ pos2 ] != *p );
@ -243,7 +243,7 @@ void find ( const char *arg ) {
void to_string ( const char *arg ) { void to_string ( const char *arg ) {
string_ref sr1; string_view sr1;
std::string str1; std::string str1;
std::string str2; std::string str2;
@ -260,17 +260,17 @@ void to_string ( const char *arg ) {
} }
void compare ( const char *arg ) { void compare ( const char *arg ) {
string_ref sr1; string_view sr1;
std::string str1; std::string str1;
std::string str2 = str1; std::string str2 = str1;
str1.assign ( arg ); str1.assign ( arg );
sr1 = arg; sr1 = arg;
BOOST_CHECK ( sr1 == sr1); // compare string_ref and string_ref BOOST_CHECK ( sr1 == sr1); // compare string_view and string_view
BOOST_CHECK ( sr1 == str1); // compare string and string_ref BOOST_CHECK ( sr1 == str1); // compare string and string_view
BOOST_CHECK ( str1 == sr1 ); // compare string_ref and string BOOST_CHECK ( str1 == sr1 ); // compare string_view and string
BOOST_CHECK ( sr1 == arg ); // compare string_ref and pointer BOOST_CHECK ( sr1 == arg ); // compare string_view and pointer
BOOST_CHECK ( arg == sr1 ); // compare pointer and string_ref BOOST_CHECK ( arg == sr1 ); // compare pointer and string_view
if ( sr1.size () > 0 ) { if ( sr1.size () > 0 ) {
(*str1.rbegin())++; (*str1.rbegin())++;

View File

@ -0,0 +1,29 @@
/*
Copyright (c) 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
*/
#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>
namespace
{
} // unnamed namespace
int main()
{
typedef boost::string_view::traits_type string_traits;
return boost::report_errors();
}

View File

@ -5,16 +5,16 @@
* http://www.boost.org/LICENSE_1_0.txt) * http://www.boost.org/LICENSE_1_0.txt)
*/ */
/*! /*!
* \file string_ref_test_io.cpp * \file string_view_test_io.cpp
* \author Andrey Semashev * \author Andrey Semashev
* \date 26.05.2013 * \date 26.05.2013
* *
* \brief This header contains tests for stream operations of \c basic_string_ref. * \brief This header contains tests for stream operations of \c basic_string_view.
*/ */
#define BOOST_TEST_MODULE string_ref_test_io #define BOOST_TEST_MODULE string_view_test_io
#include <boost/utility/string_ref.hpp> #include <boost/utility/string_view.hpp>
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
@ -60,7 +60,7 @@ struct context
context() context()
{ {
boost::string_ref str = test_strings[0]; boost::string_view str = test_strings[0];
std::copy(str.begin(), str.end(), std::back_inserter(begin)); std::copy(str.begin(), str.end(), std::back_inserter(begin));
str = test_strings[1]; str = test_strings[1];
@ -72,17 +72,17 @@ struct context
}; };
// Test regular output // Test regular output
BOOST_AUTO_TEST_CASE_TEMPLATE(string_ref_output, CharT, char_types) BOOST_AUTO_TEST_CASE_TEMPLATE(string_view_output, CharT, char_types)
{ {
typedef CharT char_type; typedef CharT char_type;
typedef std::basic_string< char_type > string_type; typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type; typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type; typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx; context< char_type > ctx;
ostream_type strm; ostream_type strm;
strm << string_ref_type(ctx.abcd); strm << string_view_type(ctx.abcd);
BOOST_CHECK(strm.str() == ctx.abcd); BOOST_CHECK(strm.str() == ctx.abcd);
} }
@ -92,41 +92,41 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(padding, CharT, char_types)
typedef CharT char_type; typedef CharT char_type;
typedef std::basic_string< char_type > string_type; typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type; typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type; typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx; context< char_type > ctx;
// Test for padding // Test for padding
{ {
ostream_type strm_ref; ostream_type strm_view;
strm_ref << ctx.begin << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; strm_view << ctx.begin << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct; ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end; strm_correct << ctx.begin << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str()); BOOST_CHECK(strm_view.str() == strm_correct.str());
} }
// Test for long padding // Test for long padding
{ {
ostream_type strm_ref; ostream_type strm_view;
strm_ref << ctx.begin << std::setw(100) << string_ref_type(ctx.abcd) << ctx.end; strm_view << ctx.begin << std::setw(100) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct; ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end; strm_correct << ctx.begin << std::setw(100) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str()); BOOST_CHECK(strm_view.str() == strm_correct.str());
} }
// Test that short width does not truncate the string // Test that short width does not truncate the string
{ {
ostream_type strm_ref; ostream_type strm_view;
strm_ref << ctx.begin << std::setw(1) << string_ref_type(ctx.abcd) << ctx.end; strm_view << ctx.begin << std::setw(1) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct; ostream_type strm_correct;
strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end; strm_correct << ctx.begin << std::setw(1) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str()); BOOST_CHECK(strm_view.str() == strm_correct.str());
} }
} }
@ -136,17 +136,17 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(padding_fill, CharT, char_types)
typedef CharT char_type; typedef CharT char_type;
typedef std::basic_string< char_type > string_type; typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type; typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type; typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx; context< char_type > ctx;
ostream_type strm_ref; ostream_type strm_view;
strm_ref << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; 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; ostream_type strm_correct;
strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end; strm_correct << ctx.begin << std::setfill(static_cast< char_type >('x')) << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str()); BOOST_CHECK(strm_view.str() == strm_correct.str());
} }
// Test support for alignment // Test support for alignment
@ -155,29 +155,29 @@ BOOST_AUTO_TEST_CASE_TEMPLATE(alignment, CharT, char_types)
typedef CharT char_type; typedef CharT char_type;
typedef std::basic_string< char_type > string_type; typedef std::basic_string< char_type > string_type;
typedef std::basic_ostringstream< char_type > ostream_type; typedef std::basic_ostringstream< char_type > ostream_type;
typedef boost::basic_string_ref< char_type > string_ref_type; typedef boost::basic_string_view< char_type > string_view_type;
context< char_type > ctx; context< char_type > ctx;
// Left alignment // Left alignment
{ {
ostream_type strm_ref; ostream_type strm_view;
strm_ref << ctx.begin << std::left << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; strm_view << ctx.begin << std::left << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct; ostream_type strm_correct;
strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end; strm_correct << ctx.begin << std::left << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str()); BOOST_CHECK(strm_view.str() == strm_correct.str());
} }
// Right alignment // Right alignment
{ {
ostream_type strm_ref; ostream_type strm_view;
strm_ref << ctx.begin << std::right << std::setw(8) << string_ref_type(ctx.abcd) << ctx.end; strm_view << ctx.begin << std::right << std::setw(8) << string_view_type(ctx.abcd) << ctx.end;
ostream_type strm_correct; ostream_type strm_correct;
strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end; strm_correct << ctx.begin << std::right << std::setw(8) << ctx.abcd << ctx.end;
BOOST_CHECK(strm_ref.str() == strm_correct.str()); BOOST_CHECK(strm_view.str() == strm_correct.str());
} }
} }