• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2    Copyright (c) Marshall Clow 2012-2012.
3 
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)
6 
7     For more information, see http://www.boost.org
8 */
9 
10 #include <new>        // for placement new
11 #include <iostream>
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
15 
16 #include <boost/utility/string_view.hpp>
17 #include <boost/config.hpp>
18 
19 #include <boost/core/lightweight_test.hpp>
20 
21 typedef boost::string_view string_view;
22 
ends_with(const char * arg)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 );
27     const char *p = arg;
28 
29     while ( *p ) {
30         BOOST_TEST ( sr.ends_with ( p ));
31         ++p;
32         }
33 
34     while ( !sr2.empty ()) {
35         BOOST_TEST ( sr.ends_with ( sr2 ));
36         sr2.remove_prefix (1);
37         }
38 
39     sr2 = arg;
40     while ( !sr2.empty ()) {
41         BOOST_TEST ( sr.ends_with ( sr2 ));
42         sr2.remove_prefix (1);
43         }
44 
45     char ch = sz == 0 ? '\0' : arg [ sz - 1 ];
46     sr2 = arg;
47     if ( sz > 0 )
48       BOOST_TEST ( sr2.ends_with ( ch ));
49     BOOST_TEST ( !sr2.ends_with ( ++ch ));
50     BOOST_TEST ( sr2.ends_with ( string_view()));
51     }
52 
starts_with(const char * arg)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;
58     while ( p >= arg ) {
59         std::string foo ( arg, p + 1 );
60         BOOST_TEST ( sr.starts_with ( foo ));
61         --p;
62         }
63 
64     while ( !sr2.empty ()) {
65         BOOST_TEST ( sr.starts_with ( sr2 ));
66         sr2.remove_suffix (1);
67         }
68 
69     char ch = *arg;
70     sr2 = arg;
71   if ( sz > 0 )
72     BOOST_TEST ( sr2.starts_with ( ch ));
73     BOOST_TEST ( !sr2.starts_with ( ++ch ));
74     BOOST_TEST ( sr2.starts_with ( string_view ()));
75     }
76 
reverse(const char * arg)77 void reverse ( const char *arg ) {
78 //  Round trip
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 ());
83 
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 ()));
87     }
88 
89 //  This helper function eliminates signed vs. unsigned warnings
ptr_diff(const char * res,const char * base)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 );
93     }
94 
find(const char * arg)95 void find ( const char *arg ) {
96     string_view sr1;
97     string_view sr2;
98     const char *p;
99 
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 );
103 
104 //  Look for each character in the string(searching from the start)
105     p = arg;
106     sr1 = arg;
107     while ( *p ) {
108       string_view::size_type pos = sr1.find(*p);
109       BOOST_TEST ( pos != string_view::npos && ( pos <= ptr_diff ( p, arg )));
110       ++p;
111       }
112 
113 //  Look for each character in the string (searching from the end)
114     p = arg;
115     sr1 = arg;
116     while ( *p ) {
117       string_view::size_type pos = sr1.rfind(*p);
118       BOOST_TEST ( pos != string_view::npos && pos < sr1.size () && ( pos >= ptr_diff ( p, arg )));
119       ++p;
120       }
121 
122 //  Look for pairs on characters (searching from the start)
123     sr1 = arg;
124     p = arg;
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 ));
129         p++;
130         }
131 
132     sr1 = arg;
133     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 ));
140         if ( strp != NULL )
141             BOOST_TEST ( ptr_diff ( strp, arg ) == pos );
142     }
143 
144     sr1 = arg;
145     p = arg;
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 ));
152         if ( strp != NULL )
153             BOOST_TEST ( ptr_diff ( strp, arg ) == pos );
154     }
155 
156 
157 //  Find everything at the start
158     p = arg;
159     sr1 = arg;
160     while ( !sr1.empty ()) {
161         string_view::size_type pos = sr1.find(*p);
162         BOOST_TEST ( pos == 0 );
163         sr1.remove_prefix (1);
164         ++p;
165         }
166 
167 //  Find everything at the end
168     sr1  = arg;
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);
174         --p;
175         }
176 
177 //  Find everything at the start
178     sr1  = arg;
179     p    = arg;
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);
184         ++p;
185         }
186 
187 
188 //  Find everything at the end
189     sr1  = arg;
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);
195         --p;
196         }
197 
198 //  Basic sanity checking for "find_first_of / find_first_not_of"
199     sr1 = arg;
200     sr2 = arg;
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 );
205         }
206 
207     p = arg;
208     sr1 = arg;
209     while ( *p ) {
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 );
217             }
218 
219         BOOST_TEST ( pos2 != pos1 );
220         ++p;
221         }
222 
223 //  Basic sanity checking for "find_last_of / find_last_not_of"
224     sr1 = arg;
225     sr2 = arg;
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 );
230         }
231 
232     p = arg;
233     sr1 = arg;
234     while ( *p ) {
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 );
243             }
244 
245         BOOST_TEST ( pos2 != pos1 );
246         ++p;
247         }
248 
249     }
250 
251 template <typename T>
252 class custom_allocator {
253 public:
254     typedef T value_type;
255     typedef T* pointer;
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;
263 
264     template<class U>
265     struct rebind {
266         typedef custom_allocator<U> other;
267         };
268 
custom_allocator()269     custom_allocator() BOOST_NOEXCEPT {}
270     template <typename U>
custom_allocator(custom_allocator<U> const &)271     custom_allocator(custom_allocator<U> const&) BOOST_NOEXCEPT {}
272 
allocate(size_type n) const273     pointer allocate(size_type n) const {
274         return static_cast<pointer>(std::malloc(sizeof(value_type) * n));
275         }
deallocate(pointer p,size_type) const276     void deallocate(pointer p, size_type) const BOOST_NOEXCEPT {
277         std::free(p);
278         }
279 
address(reference value) const280     pointer address(reference value) const BOOST_NOEXCEPT {
281         return &value;
282         }
283 
address(const_reference value) const284     const_pointer address(const_reference value) const BOOST_NOEXCEPT {
285         return &value;
286         }
287 
max_size() const288     BOOST_CONSTEXPR size_type max_size() const BOOST_NOEXCEPT {
289         return (~(size_type)0u) / sizeof(value_type);
290         }
291 
292 #if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
293 #if !defined(BOOST_NO_CXX11_VARIADIC_TEMPLATES)
294     template <class U, class... Args>
construct(U * ptr,Args &&...args) const295     void construct(U* ptr, Args&&... args) const {
296         ::new((void*)ptr) U(static_cast<Args&&>(args)...);
297         }
298 #else
299     template <class U, class V>
construct(U * ptr,V && value) const300     void construct(U* ptr, V&& value) const {
301         ::new((void*)ptr) U(static_cast<V&&>(value));
302         }
303 #endif
304 #else
305     template <class U, class V>
construct(U * ptr,const V & value) const306     void construct(U* ptr, const V& value) const {
307         ::new((void*)ptr) U(value);
308         }
309 #endif
310 
311     template <class U>
construct(U * ptr) const312     void construct(U* ptr) const {
313         ::new((void*)ptr) U();
314         }
315 
316     template <class U>
destroy(U * ptr) const317     void destroy(U* ptr) const {
318         (void)ptr;
319         ptr->~U();
320         }
321     };
322 
323 template <typename T, typename U>
operator ==(const custom_allocator<T> &,const custom_allocator<U> &)324 BOOST_CONSTEXPR bool operator==(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT {
325     return true;
326     }
327 template <typename T, typename U>
operator !=(const custom_allocator<T> &,const custom_allocator<U> &)328 BOOST_CONSTEXPR bool operator!=(const custom_allocator<T> &, const custom_allocator<U> &) BOOST_NOEXCEPT {
329     return false;
330     }
331 
to_string(const char * arg)332 void to_string ( const char *arg ) {
333     string_view sr1;
334     std::string str1;
335     std::string str2;
336 
337     str1.assign ( arg );
338     sr1 = arg;
339 //  str2 = sr1.to_string<std::allocator<char> > ();
340     str2 = sr1.to_string ();
341     BOOST_TEST ( str1 == str2 );
342 
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 );
345 
346 #ifndef BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS
347     std::string str4 = static_cast<std::string> ( sr1 );
348     BOOST_TEST ( str1 == str4 );
349 #endif
350     }
351 
compare(const char * arg)352 void compare ( const char *arg ) {
353     string_view sr1;
354     std::string str1;
355     std::string str2 = str1;
356 
357     str1.assign ( arg );
358     sr1 = arg;
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
364 
365     if ( sr1.size () > 0 ) {
366         (*str1.rbegin())++;
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 );
373 
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 );
381         }
382     }
383 
384 const char *test_strings [] = {
385     "",
386     "0",
387     "abc",
388     "AAA",  // all the same
389     "adsfadadiaef;alkdg;aljt;j agl;sjrl;tjs;lga;lretj;srg[w349u5209dsfadfasdfasdfadsf",
390     "abc\0asdfadsfasf",
391     NULL
392     };
393 
main()394 int main()
395 {
396     const char **p = &test_strings[0];
397 
398     while ( *p != NULL ) {
399         starts_with ( *p );
400         ends_with ( *p );
401         reverse ( *p );
402         find ( *p );
403         to_string ( *p );
404         compare ( *p );
405 
406         p++;
407         }
408 
409     return boost::report_errors();
410 }
411