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 // Look for each character in the string(searching from the start)
104 string_view::size_type pos
= sr1
.find(*p
);
105 BOOST_TEST ( pos
!= string_view::npos
&& ( pos
<= ptr_diff ( p
, arg
)));
109 // Look for each character in the string (searching from the end)
113 string_view::size_type pos
= sr1
.rfind(*p
);
114 BOOST_TEST ( pos
!= string_view::npos
&& pos
< sr1
.size () && ( pos
>= ptr_diff ( p
, arg
)));
118 // Look for pairs on characters (searching from the start)
121 while ( *p
&& *(p
+1)) {
122 string_view
sr3 ( p
, 2 );
123 string_view::size_type pos
= sr1
.find ( sr3
);
124 BOOST_TEST ( pos
!= string_view::npos
&& pos
<= static_cast<string_view::size_type
>( p
- arg
));
130 // for all possible chars, see if we find them in the right place.
131 // Note that strchr will/might do the _wrong_ thing if we search for NULL
132 for ( int ch
= 1; ch
< 256; ++ch
) {
133 string_view::size_type pos
= sr1
.find(ch
);
134 const char *strp
= std::strchr ( arg
, ch
);
135 BOOST_TEST (( strp
== NULL
) == ( pos
== string_view::npos
));
137 BOOST_TEST ( ptr_diff ( strp
, arg
) == pos
);
142 // for all possible chars, see if we find them in the right place.
143 // Note that strchr will/might do the _wrong_ thing if we search for NULL
144 for ( int ch
= 1; ch
< 256; ++ch
) {
145 string_view::size_type pos
= sr1
.rfind(ch
);
146 const char *strp
= std::strrchr ( arg
, ch
);
147 BOOST_TEST (( strp
== NULL
) == ( pos
== string_view::npos
));
149 BOOST_TEST ( ptr_diff ( strp
, arg
) == pos
);
153 // Find everything at the start
156 while ( !sr1
.empty ()) {
157 string_view::size_type pos
= sr1
.find(*p
);
158 BOOST_TEST ( pos
== 0 );
159 sr1
.remove_prefix (1);
163 // Find everything at the end
165 p
= arg
+ std::strlen ( arg
) - 1;
166 while ( !sr1
.empty ()) {
167 string_view::size_type pos
= sr1
.rfind(*p
);
168 BOOST_TEST ( pos
== sr1
.size () - 1 );
169 sr1
.remove_suffix (1);
173 // Find everything at the start
176 while ( !sr1
.empty ()) {
177 string_view::size_type pos
= sr1
.find_first_of(*p
);
178 BOOST_TEST ( pos
== 0 );
179 sr1
.remove_prefix (1);
184 // Find everything at the end
186 p
= arg
+ std::strlen ( arg
) - 1;
187 while ( !sr1
.empty ()) {
188 string_view::size_type pos
= sr1
.find_last_of(*p
);
189 BOOST_TEST ( pos
== sr1
.size () - 1 );
190 sr1
.remove_suffix (1);
194 // Basic sanity checking for "find_first_of / find_first_not_of"
197 while ( !sr1
.empty() ) {
198 BOOST_TEST ( sr1
.find_first_of ( sr2
) == 0 );
199 BOOST_TEST ( sr1
.find_first_not_of ( sr2
) == string_view::npos
);
200 sr1
.remove_prefix ( 1 );
206 string_view::size_type pos1
= sr1
.find_first_of(*p
);
207 string_view::size_type pos2
= sr1
.find_first_not_of(*p
);
208 BOOST_TEST ( pos1
!= string_view::npos
&& pos1
< sr1
.size () && pos1
<= ptr_diff ( p
, arg
));
209 if ( pos2
!= string_view::npos
) {
210 for ( size_t i
= 0 ; i
< pos2
; ++i
)
211 BOOST_TEST ( sr1
[i
] == *p
);
212 BOOST_TEST ( sr1
[ pos2
] != *p
);
215 BOOST_TEST ( pos2
!= pos1
);
219 // Basic sanity checking for "find_last_of / find_last_not_of"
222 while ( !sr1
.empty() ) {
223 BOOST_TEST ( sr1
.find_last_of ( sr2
) == ( sr1
.size () - 1 ));
224 BOOST_TEST ( sr1
.find_last_not_of ( sr2
) == string_view::npos
);
225 sr1
.remove_suffix ( 1 );
231 string_view::size_type pos1
= sr1
.find_last_of(*p
);
232 string_view::size_type pos2
= sr1
.find_last_not_of(*p
);
233 BOOST_TEST ( pos1
!= string_view::npos
&& pos1
< sr1
.size () && pos1
>= ptr_diff ( p
, arg
));
234 BOOST_TEST ( pos2
== string_view::npos
|| pos1
< sr1
.size ());
235 if ( pos2
!= string_view::npos
) {
236 for ( size_t i
= sr1
.size () -1 ; i
> pos2
; --i
)
237 BOOST_TEST ( sr1
[i
] == *p
);
238 BOOST_TEST ( sr1
[ pos2
] != *p
);
241 BOOST_TEST ( pos2
!= pos1
);
247 template <typename T
>
248 class custom_allocator
{
250 typedef T value_type
;
252 typedef const T
* const_pointer
;
253 typedef void* void_pointer
;
254 typedef const void* const_void_pointer
;
255 typedef std::size_t size_type
;
256 typedef std::ptrdiff_t difference_type
;
257 typedef T
& reference
;
258 typedef const T
& const_reference
;
262 typedef custom_allocator
<U
> other
;
265 custom_allocator() BOOST_NOEXCEPT
{}
266 template <typename U
>
267 custom_allocator(custom_allocator
<U
> const&) BOOST_NOEXCEPT
{}
269 pointer
allocate(size_type n
) const {
270 return static_cast<pointer
>(std::malloc(sizeof(value_type
) * n
));
272 void deallocate(pointer p
, size_type
) const BOOST_NOEXCEPT
{
276 pointer
address(reference value
) const BOOST_NOEXCEPT
{
280 const_pointer
address(const_reference value
) const BOOST_NOEXCEPT
{
284 BOOST_CONSTEXPR size_type
max_size() const BOOST_NOEXCEPT
{
285 return (~(size_type
)0u) / sizeof(value_type
);
288 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
289 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
290 template <class U
, class... Args
>
291 void construct(U
* ptr
, Args
&&... args
) const {
292 ::new((void*)ptr
) U(static_cast<Args
&&>(args
)...);
295 template <class U
, class V
>
296 void construct(U
* ptr
, V
&& value
) const {
297 ::new((void*)ptr
) U(static_cast<V
&&>(value
));
301 template <class U
, class V
>
302 void construct(U
* ptr
, const V
& value
) const {
303 ::new((void*)ptr
) U(value
);
308 void construct(U
* ptr
) const {
309 ::new((void*)ptr
) U();
313 void destroy(U
* ptr
) const {
319 template <typename T
, typename U
>
320 BOOST_CONSTEXPR
bool operator==(const custom_allocator
<T
> &, const custom_allocator
<U
> &) BOOST_NOEXCEPT
{
323 template <typename T
, typename U
>
324 BOOST_CONSTEXPR
bool operator!=(const custom_allocator
<T
> &, const custom_allocator
<U
> &) BOOST_NOEXCEPT
{
328 void to_string ( const char *arg
) {
335 // str2 = sr1.to_string<std::allocator<char> > ();
336 str2
= sr1
.to_string ();
337 BOOST_TEST ( str1
== str2
);
339 std::basic_string
<char, std::char_traits
<char>, custom_allocator
<char> > str3
= sr1
.to_string(custom_allocator
<char>());
340 BOOST_TEST ( std::strcmp(str1
.c_str(), str3
.c_str()) == 0 );
342 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
343 std::string str4
= static_cast<std::string
> ( sr1
);
344 BOOST_TEST ( str1
== str4
);
348 void compare ( const char *arg
) {
351 std::string str2
= str1
;
355 BOOST_TEST ( sr1
== sr1
); // compare string_view and string_view
356 BOOST_TEST ( sr1
== str1
); // compare string and string_view
357 BOOST_TEST ( str1
== sr1
); // compare string_view and string
358 BOOST_TEST ( sr1
== arg
); // compare string_view and pointer
359 BOOST_TEST ( arg
== sr1
); // compare pointer and string_view
361 if ( sr1
.size () > 0 ) {
363 BOOST_TEST ( sr1
!= str1
);
364 BOOST_TEST ( str1
!= sr1
);
365 BOOST_TEST ( sr1
< str1
);
366 BOOST_TEST ( sr1
<= str1
);
367 BOOST_TEST ( str1
> sr1
);
368 BOOST_TEST ( str1
>= sr1
);
370 (*str1
.rbegin()) -= 2;
371 BOOST_TEST ( sr1
!= str1
);
372 BOOST_TEST ( str1
!= sr1
);
373 BOOST_TEST ( sr1
> str1
);
374 BOOST_TEST ( sr1
>= str1
);
375 BOOST_TEST ( str1
< sr1
);
376 BOOST_TEST ( str1
<= sr1
);
380 const char *test_strings
[] = {
384 "AAA", // all the same
385 "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
392 const char **p
= &test_strings
[0];
394 while ( *p
!= NULL
) {
405 return boost::report_errors();