2 Copyright (c) Marshall Clow 2012-2012.
4 Distributed under the Boost Software License, Version 1.0. (See accompanying
5 file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 For more information, see http://www.boost.org
10 #include <new> // for placement new
12 #include <cstddef> // for NULL, std::size_t, std::ptrdiff_t
13 #include <cstring> // for std::strchr and std::strcmp
14 #include <cstdlib> // for std::malloc and std::free
16 #include <boost/utility/string_view.hpp>
17 #include <boost/config.hpp>
19 #include <boost/core/lightweight_test.hpp>
21 typedef boost::string_view string_view
;
23 void ends_with ( const char *arg
) {
24 const size_t sz
= std::strlen ( arg
);
25 string_view
sr ( arg
);
26 string_view
sr2 ( arg
);
30 BOOST_TEST ( sr
.ends_with ( p
));
34 while ( !sr2
.empty ()) {
35 BOOST_TEST ( sr
.ends_with ( sr2
));
36 sr2
.remove_prefix (1);
40 while ( !sr2
.empty ()) {
41 BOOST_TEST ( sr
.ends_with ( sr2
));
42 sr2
.remove_prefix (1);
45 char ch
= sz
== 0 ? '\0' : arg
[ sz
- 1 ];
48 BOOST_TEST ( sr2
.ends_with ( ch
));
49 BOOST_TEST ( !sr2
.ends_with ( ++ch
));
50 BOOST_TEST ( sr2
.ends_with ( string_view()));
53 void starts_with ( const char *arg
) {
54 const size_t sz
= std::strlen ( arg
);
55 string_view
sr ( arg
);
56 string_view
sr2 ( arg
);
57 const char *p
= arg
+ std::strlen ( arg
) - 1;
59 std::string
foo ( arg
, p
+ 1 );
60 BOOST_TEST ( sr
.starts_with ( foo
));
64 while ( !sr2
.empty ()) {
65 BOOST_TEST ( sr
.starts_with ( sr2
));
66 sr2
.remove_suffix (1);
72 BOOST_TEST ( sr2
.starts_with ( ch
));
73 BOOST_TEST ( !sr2
.starts_with ( ++ch
));
74 BOOST_TEST ( sr2
.starts_with ( string_view ()));
77 void reverse ( const char *arg
) {
79 string_view
sr1 ( arg
);
80 std::string
string1 ( sr1
.rbegin (), sr1
.rend ());
81 string_view
sr2 ( string1
);
82 std::string
string2 ( sr2
.rbegin (), sr2
.rend ());
84 BOOST_TEST ( std::equal ( sr2
.rbegin (), sr2
.rend (), arg
));
85 BOOST_TEST ( string2
== arg
);
86 BOOST_TEST ( std::equal ( sr1
.begin (), sr1
.end (), string2
.begin ()));
89 // This helper function eliminates signed vs. unsigned warnings
90 string_view::size_type
ptr_diff ( const char *res
, const char *base
) {
91 BOOST_TEST ( res
>= base
);
92 return static_cast<string_view::size_type
> ( res
- base
);
95 void find ( const char *arg
) {
100 // When we search for the empty string, we find it at position 0
101 BOOST_TEST ( sr1
.find (sr2
) == 0 );
102 BOOST_TEST ( sr1
.rfind(sr2
) == 0 );
104 // Look for each character in the string(searching from the start)
108 string_view::size_type pos
= sr1
.find(*p
);
109 BOOST_TEST ( pos
!= string_view::npos
&& ( pos
<= ptr_diff ( p
, arg
)));
113 // Look for each character in the string (searching from the end)
117 string_view::size_type pos
= sr1
.rfind(*p
);
118 BOOST_TEST ( pos
!= string_view::npos
&& pos
< sr1
.size () && ( pos
>= ptr_diff ( p
, arg
)));
122 // Look for pairs on characters (searching from the start)
125 while ( *p
&& *(p
+1)) {
126 string_view
sr3 ( p
, 2 );
127 string_view::size_type pos
= sr1
.find ( sr3
);
128 BOOST_TEST ( pos
!= string_view::npos
&& pos
<= static_cast<string_view::size_type
>( p
- arg
));
134 // for all possible chars, see if we find them in the right place.
135 // Note that strchr will/might do the _wrong_ thing if we search for NULL
136 for ( int ch
= 1; ch
< 256; ++ch
) {
137 string_view::size_type pos
= sr1
.find(ch
);
138 const char *strp
= std::strchr ( arg
, ch
);
139 BOOST_TEST (( strp
== NULL
) == ( pos
== string_view::npos
));
141 BOOST_TEST ( ptr_diff ( strp
, arg
) == pos
);
146 // for all possible chars, see if we find them in the right place.
147 // Note that strchr will/might do the _wrong_ thing if we search for NULL
148 for ( int ch
= 1; ch
< 256; ++ch
) {
149 string_view::size_type pos
= sr1
.rfind(ch
);
150 const char *strp
= std::strrchr ( arg
, ch
);
151 BOOST_TEST (( strp
== NULL
) == ( pos
== string_view::npos
));
153 BOOST_TEST ( ptr_diff ( strp
, arg
) == pos
);
157 // Find everything at the start
160 while ( !sr1
.empty ()) {
161 string_view::size_type pos
= sr1
.find(*p
);
162 BOOST_TEST ( pos
== 0 );
163 sr1
.remove_prefix (1);
167 // Find everything at the end
169 p
= arg
+ std::strlen ( arg
) - 1;
170 while ( !sr1
.empty ()) {
171 string_view::size_type pos
= sr1
.rfind(*p
);
172 BOOST_TEST ( pos
== sr1
.size () - 1 );
173 sr1
.remove_suffix (1);
177 // Find everything at the start
180 while ( !sr1
.empty ()) {
181 string_view::size_type pos
= sr1
.find_first_of(*p
);
182 BOOST_TEST ( pos
== 0 );
183 sr1
.remove_prefix (1);
188 // Find everything at the end
190 p
= arg
+ std::strlen ( arg
) - 1;
191 while ( !sr1
.empty ()) {
192 string_view::size_type pos
= sr1
.find_last_of(*p
);
193 BOOST_TEST ( pos
== sr1
.size () - 1 );
194 sr1
.remove_suffix (1);
198 // Basic sanity checking for "find_first_of / find_first_not_of"
201 while ( !sr1
.empty() ) {
202 BOOST_TEST ( sr1
.find_first_of ( sr2
) == 0 );
203 BOOST_TEST ( sr1
.find_first_not_of ( sr2
) == string_view::npos
);
204 sr1
.remove_prefix ( 1 );
210 string_view::size_type pos1
= sr1
.find_first_of(*p
);
211 string_view::size_type pos2
= sr1
.find_first_not_of(*p
);
212 BOOST_TEST ( pos1
!= string_view::npos
&& pos1
< sr1
.size () && pos1
<= ptr_diff ( p
, arg
));
213 if ( pos2
!= string_view::npos
) {
214 for ( size_t i
= 0 ; i
< pos2
; ++i
)
215 BOOST_TEST ( sr1
[i
] == *p
);
216 BOOST_TEST ( sr1
[ pos2
] != *p
);
219 BOOST_TEST ( pos2
!= pos1
);
223 // Basic sanity checking for "find_last_of / find_last_not_of"
226 while ( !sr1
.empty() ) {
227 BOOST_TEST ( sr1
.find_last_of ( sr2
) == ( sr1
.size () - 1 ));
228 BOOST_TEST ( sr1
.find_last_not_of ( sr2
) == string_view::npos
);
229 sr1
.remove_suffix ( 1 );
235 string_view::size_type pos1
= sr1
.find_last_of(*p
);
236 string_view::size_type pos2
= sr1
.find_last_not_of(*p
);
237 BOOST_TEST ( pos1
!= string_view::npos
&& pos1
< sr1
.size () && pos1
>= ptr_diff ( p
, arg
));
238 BOOST_TEST ( pos2
== string_view::npos
|| pos1
< sr1
.size ());
239 if ( pos2
!= string_view::npos
) {
240 for ( size_t i
= sr1
.size () -1 ; i
> pos2
; --i
)
241 BOOST_TEST ( sr1
[i
] == *p
);
242 BOOST_TEST ( sr1
[ pos2
] != *p
);
245 BOOST_TEST ( pos2
!= pos1
);
251 template <typename T
>
252 class custom_allocator
{
254 typedef T value_type
;
256 typedef const T
* const_pointer
;
257 typedef void* void_pointer
;
258 typedef const void* const_void_pointer
;
259 typedef std::size_t size_type
;
260 typedef std::ptrdiff_t difference_type
;
261 typedef T
& reference
;
262 typedef const T
& const_reference
;
266 typedef custom_allocator
<U
> other
;
269 custom_allocator() BOOST_NOEXCEPT
{}
270 template <typename U
>
271 custom_allocator(custom_allocator
<U
> const&) BOOST_NOEXCEPT
{}
273 pointer
allocate(size_type n
) const {
274 return static_cast<pointer
>(std::malloc(sizeof(value_type
) * n
));
276 void deallocate(pointer p
, size_type
) const BOOST_NOEXCEPT
{
280 pointer
address(reference value
) const BOOST_NOEXCEPT
{
284 const_pointer
address(const_reference value
) const BOOST_NOEXCEPT
{
288 BOOST_CONSTEXPR size_type
max_size() const BOOST_NOEXCEPT
{
289 return (~(size_type
)0u) / sizeof(value_type
);
292 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
293 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
294 template <class U
, class... Args
>
295 void construct(U
* ptr
, Args
&&... args
) const {
296 ::new((void*)ptr
) U(static_cast<Args
&&>(args
)...);
299 template <class U
, class V
>
300 void construct(U
* ptr
, V
&& value
) const {
301 ::new((void*)ptr
) U(static_cast<V
&&>(value
));
305 template <class U
, class V
>
306 void construct(U
* ptr
, const V
& value
) const {
307 ::new((void*)ptr
) U(value
);
312 void construct(U
* ptr
) const {
313 ::new((void*)ptr
) U();
317 void destroy(U
* ptr
) const {
323 template <typename T
, typename U
>
324 BOOST_CONSTEXPR
bool operator==(const custom_allocator
<T
> &, const custom_allocator
<U
> &) BOOST_NOEXCEPT
{
327 template <typename T
, typename U
>
328 BOOST_CONSTEXPR
bool operator!=(const custom_allocator
<T
> &, const custom_allocator
<U
> &) BOOST_NOEXCEPT
{
332 void to_string ( const char *arg
) {
339 // str2 = sr1.to_string<std::allocator<char> > ();
340 str2
= sr1
.to_string ();
341 BOOST_TEST ( str1
== str2
);
343 std::basic_string
<char, std::char_traits
<char>, custom_allocator
<char> > str3
= sr1
.to_string(custom_allocator
<char>());
344 BOOST_TEST ( std::strcmp(str1
.c_str(), str3
.c_str()) == 0 );
346 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
347 std::string str4
= static_cast<std::string
> ( sr1
);
348 BOOST_TEST ( str1
== str4
);
352 void compare ( const char *arg
) {
355 std::string str2
= str1
;
359 BOOST_TEST ( sr1
== sr1
); // compare string_view and string_view
360 BOOST_TEST ( sr1
== str1
); // compare string and string_view
361 BOOST_TEST ( str1
== sr1
); // compare string_view and string
362 BOOST_TEST ( sr1
== arg
); // compare string_view and pointer
363 BOOST_TEST ( arg
== sr1
); // compare pointer and string_view
365 if ( sr1
.size () > 0 ) {
367 BOOST_TEST ( sr1
!= str1
);
368 BOOST_TEST ( str1
!= sr1
);
369 BOOST_TEST ( sr1
< str1
);
370 BOOST_TEST ( sr1
<= str1
);
371 BOOST_TEST ( str1
> sr1
);
372 BOOST_TEST ( str1
>= sr1
);
374 (*str1
.rbegin()) -= 2;
375 BOOST_TEST ( sr1
!= str1
);
376 BOOST_TEST ( str1
!= sr1
);
377 BOOST_TEST ( sr1
> str1
);
378 BOOST_TEST ( sr1
>= str1
);
379 BOOST_TEST ( str1
< sr1
);
380 BOOST_TEST ( str1
<= sr1
);
384 const char *test_strings
[] = {
388 "AAA", // all the same
389 "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
396 const char **p
= &test_strings
[0];
398 while ( *p
!= NULL
) {
409 return boost::report_errors();