1 //////////////////////////////////////////////////////////////////////////////
3 // (C) Copyright Ion Gaztanaga 2004-2013. Distributed under the Boost
4 // Software License, Version 1.0. (See accompanying file
5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 // See http://www.boost.org/libs/container for documentation.
9 //////////////////////////////////////////////////////////////////////////////
11 #include <boost/container/detail/config_begin.hpp>
12 #include <boost/container/vector.hpp>
13 #include <boost/container/string.hpp>
16 #include <boost/container/detail/algorithm.hpp> //equal()
21 #include "dummy_test_allocator.hpp"
22 #include "check_equal_containers.hpp"
23 #include "expand_bwd_test_allocator.hpp"
24 #include "expand_bwd_test_template.hpp"
25 #include "propagate_allocator_test.hpp"
26 #include "default_init_test.hpp"
27 #include "comparison_test.hpp"
28 #include "../../intrusive/test/iterator_test.hpp"
29 #include <boost/utility/string_view.hpp>
30 #include <boost/core/lightweight_test.hpp>
32 using namespace boost::container
;
36 template<class Str1
, class Str2
>
37 bool operator ()(const Str1
&string1
, const Str2
&string2
) const
39 if(string1
.size() != string2
.size())
41 return std::char_traits
<typename
Str1::value_type
>::compare
42 (string1
.c_str(), string2
.c_str(), string1
.size()) == 0;
46 //Function to check if both lists are equal
47 template<class StrVector1
, class StrVector2
>
48 bool CheckEqualStringVector(StrVector1
*strvect1
, StrVector2
*strvect2
)
51 return boost::container::algo_equal(strvect1
->begin(), strvect1
->end(),
52 strvect2
->begin(), comp
);
55 template<class ForwardIt
>
56 ForwardIt
unique(ForwardIt first
, ForwardIt
const last
)
60 //Find first adjacent pair
65 else if(*first
== *i
){
70 //Now overwrite skipping adjacent elements
72 if (!(*first
== *i
)) {
73 *(++first
) = boost::move(*i
);
81 template<class CharType
>
82 struct string_literals
;
85 struct string_literals
<char>
87 static const char *String()
89 static const char *Prefix()
91 static const char *Suffix()
93 static const char *LongString()
94 { return "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
97 static void sprintf_number(char *buf
, int number
)
99 std::sprintf(buf
, "%i", number
);
104 struct string_literals
<wchar_t>
106 static const wchar_t *String()
107 { return L
"String"; }
108 static const wchar_t *Prefix()
109 { return L
"Prefix"; }
110 static const wchar_t *Suffix()
111 { return L
"Suffix"; }
112 static const wchar_t *LongString()
113 { return L
"LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
114 static wchar_t Char()
116 static void sprintf_number(wchar_t *buffer
, unsigned int number
)
118 //For compilers without wsprintf, print it backwards
119 const wchar_t *digits
= L
"0123456789";
120 wchar_t *buf
= buffer
;
123 int rem
= number
% 10;
124 number
= number
/ 10;
137 template<class CharType
>
140 typedef std::basic_string
<CharType
> StdString
;
141 typedef vector
<StdString
> StdStringVector
;
142 typedef basic_string
<CharType
> BoostString
;
143 typedef vector
<BoostString
> BoostStringVector
;
145 const int MaxSize
= 100;
148 BoostStringVector
*boostStringVect
= new BoostStringVector
;
149 StdStringVector
*stdStringVect
= new StdStringVector
;
150 BoostString auxBoostString
;
151 StdString
auxStdString(StdString(auxBoostString
.begin(), auxBoostString
.end() ));
153 CharType buffer
[20];
156 for(int i
= 0; i
< MaxSize
; ++i
){
157 auxBoostString
= string_literals
<CharType
>::String();
158 auxStdString
= string_literals
<CharType
>::String();
159 string_literals
<CharType
>::sprintf_number(buffer
, i
);
160 auxBoostString
+= buffer
;
161 auxStdString
+= buffer
;
162 boostStringVect
->push_back(auxBoostString
);
163 stdStringVect
->push_back(auxStdString
);
166 if(auxBoostString
.data() != const_cast<const BoostString
&>(auxBoostString
).data() &&
167 auxBoostString
.data() != &auxBoostString
[0])
170 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
174 //Now push back moving
175 for(int i
= 0; i
< MaxSize
; ++i
){
176 auxBoostString
= string_literals
<CharType
>::String();
177 auxStdString
= string_literals
<CharType
>::String();
178 string_literals
<CharType
>::sprintf_number(buffer
, i
);
179 auxBoostString
+= buffer
;
180 auxStdString
+= buffer
;
181 boostStringVect
->push_back(boost::move(auxBoostString
));
182 stdStringVect
->push_back(auxStdString
);
185 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
190 for(int i
= 0; i
< MaxSize
; ++i
){
191 auxBoostString
= string_literals
<CharType
>::String();
192 auxStdString
= string_literals
<CharType
>::String();
193 string_literals
<CharType
>::sprintf_number(buffer
, i
);
194 auxBoostString
+= buffer
;
195 auxStdString
+= buffer
;
196 boostStringVect
->insert(boostStringVect
->begin(), auxBoostString
);
197 stdStringVect
->insert(stdStringVect
->begin(), auxStdString
);
200 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
204 //Now push front moving
205 for(int i
= 0; i
< MaxSize
; ++i
){
206 auxBoostString
= string_literals
<CharType
>::String();
207 auxStdString
= string_literals
<CharType
>::String();
208 string_literals
<CharType
>::sprintf_number(buffer
, i
);
209 auxBoostString
+= buffer
;
210 auxStdString
+= buffer
;
211 boostStringVect
->insert(boostStringVect
->begin(), boost::move(auxBoostString
));
212 stdStringVect
->insert(stdStringVect
->begin(), auxStdString
);
215 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
219 //Now test long and short representation swapping
222 auxBoostString
= string_literals
<CharType
>::String();
223 auxStdString
= string_literals
<CharType
>::String();
224 BoostString boost_swapper
;
225 StdString std_swapper
;
226 boost_swapper
.swap(auxBoostString
);
227 std_swapper
.swap(auxStdString
);
228 if(!StringEqual()(auxBoostString
, auxStdString
))
230 if(!StringEqual()(boost_swapper
, std_swapper
))
232 boost_swapper
.swap(auxBoostString
);
233 std_swapper
.swap(auxStdString
);
234 if(!StringEqual()(auxBoostString
, auxStdString
))
236 if(!StringEqual()(boost_swapper
, std_swapper
))
240 auxBoostString
.shrink_to_fit();
241 StdString(auxStdString
).swap(auxStdString
);
242 if(!StringEqual()(auxBoostString
, auxStdString
))
245 //Reserve + shrink_to_fit
246 auxBoostString
.reserve(boost_swapper
.size()*2+1);
247 auxStdString
.reserve(std_swapper
.size()*2+1);
248 if(!StringEqual()(auxBoostString
, auxStdString
))
251 auxBoostString
.shrink_to_fit();
252 StdString(auxStdString
).swap(auxStdString
);
253 if(!StringEqual()(auxBoostString
, auxStdString
))
257 auxBoostString
= string_literals
<CharType
>::LongString();
258 auxStdString
= string_literals
<CharType
>::LongString();
259 boost_swapper
= BoostString();
260 std_swapper
= StdString();
261 boost_swapper
.swap(auxBoostString
);
262 std_swapper
.swap(auxStdString
);
263 if(!StringEqual()(auxBoostString
, auxStdString
))
265 if(!StringEqual()(boost_swapper
, std_swapper
))
267 boost_swapper
.swap(auxBoostString
);
268 std_swapper
.swap(auxStdString
);
271 auxBoostString
.shrink_to_fit();
272 StdString(auxStdString
).swap(auxStdString
);
273 if(!StringEqual()(auxBoostString
, auxStdString
))
276 auxBoostString
.clear();
277 auxStdString
.clear();
278 auxBoostString
.shrink_to_fit();
279 StdString(auxStdString
).swap(auxStdString
);
280 if(!StringEqual()(auxBoostString
, auxStdString
))
284 std::sort(boostStringVect
->begin(), boostStringVect
->end());
285 std::sort(stdStringVect
->begin(), stdStringVect
->end());
286 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
288 const CharType
*prefix
= string_literals
<CharType
>::Prefix();
289 const int prefix_size
= std::char_traits
<CharType
>::length(prefix
);
290 const CharType
*sufix
= string_literals
<CharType
>::Suffix();
292 for(int i
= 0; i
< MaxSize
; ++i
){
293 (*boostStringVect
)[i
].append(sufix
);
294 (*stdStringVect
)[i
].append(sufix
);
295 (*boostStringVect
)[i
].insert((*boostStringVect
)[i
].begin(),
296 prefix
, prefix
+ prefix_size
);
297 (*stdStringVect
)[i
].insert((*stdStringVect
)[i
].begin(),
298 prefix
, prefix
+ prefix_size
);
301 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
303 for(int i
= 0; i
< MaxSize
; ++i
){
304 std::reverse((*boostStringVect
)[i
].begin(), (*boostStringVect
)[i
].end());
305 std::reverse((*stdStringVect
)[i
].begin(), (*stdStringVect
)[i
].end());
308 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
310 for(int i
= 0; i
< MaxSize
; ++i
){
311 std::reverse((*boostStringVect
)[i
].begin(), (*boostStringVect
)[i
].end());
312 std::reverse((*stdStringVect
)[i
].begin(), (*stdStringVect
)[i
].end());
315 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
317 for(int i
= 0; i
< MaxSize
; ++i
){
318 std::sort(boostStringVect
->begin(), boostStringVect
->end());
319 std::sort(stdStringVect
->begin(), stdStringVect
->end());
322 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
324 for(int i
= 0; i
< MaxSize
; ++i
){
325 (*boostStringVect
)[i
].replace((*boostStringVect
)[i
].begin(),
326 (*boostStringVect
)[i
].end(),
327 string_literals
<CharType
>::String());
328 (*stdStringVect
)[i
].replace((*stdStringVect
)[i
].begin(),
329 (*stdStringVect
)[i
].end(),
330 string_literals
<CharType
>::String());
333 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
335 boostStringVect
->erase(::unique(boostStringVect
->begin(), boostStringVect
->end()),
336 boostStringVect
->end());
337 stdStringVect
->erase(::unique(stdStringVect
->begin(), stdStringVect
->end()),
338 stdStringVect
->end());
339 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
343 BoostString bs2
= string_literals
<CharType
>::String();
344 StdString ss2
= string_literals
<CharType
>::String();
345 BoostString bs3
= string_literals
<CharType
>::Suffix();
346 StdString ss3
= string_literals
<CharType
>::Suffix();
347 BoostString bs4
= bs2
+ bs3
;
348 StdString ss4
= ss2
+ ss3
;
349 if(!StringEqual()(bs4
, ss4
)){
353 bs4
= bs2
+ BoostString();
354 ss4
= ss2
+ StdString();
355 if(!StringEqual()(bs4
, ss4
)){
359 bs4
= BoostString() + bs2
;
360 ss4
= StdString() + ss2
;
361 if(!StringEqual()(bs4
, ss4
)){
365 bs4
= BoostString() + boost::move(bs2
);
366 ss4
= StdString() + boost::move(ss2
);
367 if(!StringEqual()(bs4
, ss4
)){
371 bs2
= string_literals
<CharType
>::String();
372 ss2
= string_literals
<CharType
>::String();
373 bs4
= boost::move(bs2
) + BoostString();
374 ss4
= boost::move(ss2
) + StdString();
375 if(!StringEqual()(bs4
, ss4
)){
379 bs2
= string_literals
<CharType
>::String();
380 ss2
= string_literals
<CharType
>::String();
381 bs4
= string_literals
<CharType
>::Prefix() + boost::move(bs2
);
382 ss4
= string_literals
<CharType
>::Prefix() + boost::move(ss2
);
383 if(!StringEqual()(bs4
, ss4
)){
387 bs2
= string_literals
<CharType
>::String();
388 ss2
= string_literals
<CharType
>::String();
389 bs4
= boost::move(bs2
) + string_literals
<CharType
>::Suffix();
390 ss4
= boost::move(ss2
) + string_literals
<CharType
>::Suffix();
391 if(!StringEqual()(bs4
, ss4
)){
395 bs2
= string_literals
<CharType
>::String();
396 ss2
= string_literals
<CharType
>::String();
397 bs4
= string_literals
<CharType
>::Prefix() + bs2
;
398 ss4
= string_literals
<CharType
>::Prefix() + ss2
;
399 if(!StringEqual()(bs4
, ss4
)){
403 bs2
= string_literals
<CharType
>::String();
404 ss2
= string_literals
<CharType
>::String();
405 bs4
= bs2
+ string_literals
<CharType
>::Suffix();
406 ss4
= ss2
+ string_literals
<CharType
>::Suffix();
407 if(!StringEqual()(bs4
, ss4
)){
411 bs2
= string_literals
<CharType
>::String();
412 ss2
= string_literals
<CharType
>::String();
413 bs4
= string_literals
<CharType
>::Char() + bs2
;
414 ss4
= string_literals
<CharType
>::Char() + ss2
;
415 if(!StringEqual()(bs4
, ss4
)){
419 bs2
= string_literals
<CharType
>::String();
420 ss2
= string_literals
<CharType
>::String();
421 bs4
= bs2
+ string_literals
<CharType
>::Char();
422 ss4
= ss2
+ string_literals
<CharType
>::Char();
423 if(!StringEqual()(bs4
, ss4
)){
427 //Check front/back/begin/end
429 if(bs4
.front() != *ss4
.begin())
432 if(bs4
.back() != *(ss4
.end()-1))
436 ss4
.erase(ss4
.end()-1);
437 if(!StringEqual()(bs4
, ss4
)){
441 if(*bs4
.begin() != *ss4
.begin())
443 if(*bs4
.cbegin() != *ss4
.begin())
445 if(*bs4
.rbegin() != *ss4
.rbegin())
447 if(*bs4
.crbegin() != *ss4
.rbegin())
449 if(*(bs4
.end()-1) != *(ss4
.end()-1))
451 if(*(bs4
.cend()-1) != *(ss4
.end()-1))
453 if(*(bs4
.rend()-1) != *(ss4
.rend()-1))
455 if(*(bs4
.crend()-1) != *(ss4
.rend()-1))
459 #ifndef BOOST_CONTAINER_NO_CXX17_CTAD
460 //Chect Constructor Template Auto Deduction
462 auto gold
= StdString(string_literals
<CharType
>::String());
463 auto test
= basic_string(gold
.begin(), gold
.end());
464 if(!StringEqual()(gold
, test
)) {
471 //When done, delete vector
472 delete boostStringVect
;
473 delete stdStringVect
;
478 bool test_expand_bwd()
480 //Now test all back insertion possibilities
481 typedef test::expand_bwd_test_allocator
<char>
483 typedef basic_string
<char, std::char_traits
<char>, allocator_type
>
485 return test::test_all_expand_bwd
<string_type
>();
488 struct boost_container_string
;
490 namespace boost
{ namespace container
{ namespace test
{
493 struct alloc_propagate_base
<boost_container_string
>
495 template <class T
, class Allocator
>
498 typedef boost::container::basic_string
<T
, std::char_traits
<T
>, Allocator
> type
;
503 }}} //namespace boost::container::test
508 if(string_test
<char>()){
512 if(string_test
<wchar_t>()){
516 ////////////////////////////////////
517 // Backwards expansion test
518 ////////////////////////////////////
519 if(!test_expand_bwd())
522 ////////////////////////////////////
523 // Allocator propagation testing
524 ////////////////////////////////////
525 if(!boost::container::test::test_propagate_allocator
<boost_container_string
>())
528 ////////////////////////////////////
530 ////////////////////////////////////
531 if(!test::default_init_test
< basic_string
<char, std::char_traits
<char>, test::default_init_allocator
<char> > >()){
532 std::cerr
<< "Default init test failed" << std::endl
;
536 if(!test::default_init_test
< basic_string
<wchar_t, std::char_traits
<wchar_t>, test::default_init_allocator
<wchar_t> > >()){
537 std::cerr
<< "Default init test failed" << std::endl
;
541 ////////////////////////////////////
543 ////////////////////////////////////
545 typedef boost::container::basic_string
<char> cont_int
;
546 cont_int a
; a
.push_back(char(1)); a
.push_back(char(2)); a
.push_back(char(3));
547 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
550 typedef boost::container::basic_string
<wchar_t> cont_int
;
551 cont_int a
; a
.push_back(wchar_t(1)); a
.push_back(wchar_t(2)); a
.push_back(wchar_t(3));
552 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
555 ////////////////////////////////////
556 // Comparison testing
557 ////////////////////////////////////
559 if(!boost::container::test::test_container_comparisons
<string
>())
561 if(!boost::container::test::test_container_comparisons
<wstring
>())
565 ////////////////////////////////////
566 // has_trivial_destructor_after_move testing
567 ////////////////////////////////////
570 typedef boost::container::basic_string
<char> cont
;
571 typedef cont::allocator_type allocator_type
;
572 typedef boost::container::allocator_traits
<allocator_type
>::pointer pointer
;
573 if (boost::has_trivial_destructor_after_move
<cont
>::value
!=
574 boost::has_trivial_destructor_after_move
<allocator_type
>::value
&&
575 boost::has_trivial_destructor_after_move
<pointer
>::value
) {
576 std::cerr
<< "has_trivial_destructor_after_move(default allocator) test failed" << std::endl
;
582 typedef boost::container::basic_string
<char, std::char_traits
<char>, std::allocator
<char> > cont
;
583 typedef cont::allocator_type allocator_type
;
584 typedef boost::container::allocator_traits
<allocator_type
>::pointer pointer
;
585 if (boost::has_trivial_destructor_after_move
<cont
>::value
!=
586 boost::has_trivial_destructor_after_move
<allocator_type
>::value
&&
587 boost::has_trivial_destructor_after_move
<pointer
>::value
) {
588 std::cerr
<< "has_trivial_destructor_after_move(std::allocator) test failed" << std::endl
;
593 return boost::report_errors();
596 #include <boost/container/detail/config_end.hpp>