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
;
34 typedef test::simple_allocator
<char> SimpleCharAllocator
;
35 typedef basic_string
<char, std::char_traits
<char>, SimpleCharAllocator
> SimpleString
;
36 typedef test::simple_allocator
<SimpleString
> SimpleStringAllocator
;
37 typedef test::simple_allocator
<wchar_t> SimpleWCharAllocator
;
38 typedef basic_string
<wchar_t, std::char_traits
<wchar_t>, SimpleWCharAllocator
> SimpleWString
;
39 typedef test::simple_allocator
<SimpleWString
> SimpleWStringAllocator
;
44 //Explicit instantiations of container::basic_string
45 template class basic_string
<char, std::char_traits
<char>, SimpleCharAllocator
>;
46 template class basic_string
<wchar_t, std::char_traits
<wchar_t>, SimpleWCharAllocator
>;
47 template class basic_string
<char, std::char_traits
<char>, std::allocator
<char> >;
48 template class basic_string
<wchar_t, std::char_traits
<wchar_t>, std::allocator
<wchar_t> >;
50 //Explicit instantiation of container::vectors of container::strings
51 template class vector
<SimpleString
, SimpleStringAllocator
>;
52 template class vector
<SimpleWString
, SimpleWStringAllocator
>;
58 template<class Str1
, class Str2
>
59 bool operator ()(const Str1
&string1
, const Str2
&string2
) const
61 if(string1
.size() != string2
.size())
63 return std::char_traits
<typename
Str1::value_type
>::compare
64 (string1
.c_str(), string2
.c_str(), string1
.size()) == 0;
68 //Function to check if both lists are equal
69 template<class StrVector1
, class StrVector2
>
70 bool CheckEqualStringVector(StrVector1
*strvect1
, StrVector2
*strvect2
)
73 return boost::container::algo_equal(strvect1
->begin(), strvect1
->end(),
74 strvect2
->begin(), comp
);
77 template<class ForwardIt
>
78 ForwardIt
unique(ForwardIt first
, ForwardIt
const last
)
82 //Find first adjacent pair
87 else if(*first
== *i
){
92 //Now overwrite skipping adjacent elements
94 if (!(*first
== *i
)) {
95 *(++first
) = boost::move(*i
);
103 template<class CharType
>
104 struct string_literals
;
107 struct string_literals
<char>
109 static const char *String()
111 static const char *Prefix()
113 static const char *Suffix()
115 static const char *LongString()
116 { return "LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
119 static void sprintf_number(char *buf
, int number
)
121 std::sprintf(buf
, "%i", number
);
126 struct string_literals
<wchar_t>
128 static const wchar_t *String()
129 { return L
"String"; }
130 static const wchar_t *Prefix()
131 { return L
"Prefix"; }
132 static const wchar_t *Suffix()
133 { return L
"Suffix"; }
134 static const wchar_t *LongString()
135 { return L
"LongLongLongLongLongLongLongLongLongLongLongLongLongString"; }
136 static wchar_t Char()
138 static void sprintf_number(wchar_t *buffer
, unsigned int number
)
140 //For compilers without wsprintf, print it backwards
141 const wchar_t *digits
= L
"0123456789";
142 wchar_t *buf
= buffer
;
145 int rem
= number
% 10;
146 number
= number
/ 10;
159 template<class CharType
>
162 typedef std::basic_string
<CharType
> StdString
;
163 typedef vector
<StdString
> StdStringVector
;
164 typedef basic_string
<CharType
> BoostString
;
165 typedef vector
<BoostString
> BoostStringVector
;
167 const int MaxSize
= 100;
170 BoostStringVector
*boostStringVect
= new BoostStringVector
;
171 StdStringVector
*stdStringVect
= new StdStringVector
;
172 BoostString auxBoostString
;
173 StdString
auxStdString(StdString(auxBoostString
.begin(), auxBoostString
.end() ));
175 CharType buffer
[20];
178 for(int i
= 0; i
< MaxSize
; ++i
){
179 auxBoostString
= string_literals
<CharType
>::String();
180 auxStdString
= string_literals
<CharType
>::String();
181 string_literals
<CharType
>::sprintf_number(buffer
, i
);
182 auxBoostString
+= buffer
;
183 auxStdString
+= buffer
;
184 boostStringVect
->push_back(auxBoostString
);
185 stdStringVect
->push_back(auxStdString
);
188 if(auxBoostString
.data() != const_cast<const BoostString
&>(auxBoostString
).data() &&
189 auxBoostString
.data() != &auxBoostString
[0])
192 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
196 //Now push back moving
197 for(int i
= 0; i
< MaxSize
; ++i
){
198 auxBoostString
= string_literals
<CharType
>::String();
199 auxStdString
= string_literals
<CharType
>::String();
200 string_literals
<CharType
>::sprintf_number(buffer
, i
);
201 auxBoostString
+= buffer
;
202 auxStdString
+= buffer
;
203 boostStringVect
->push_back(boost::move(auxBoostString
));
204 stdStringVect
->push_back(auxStdString
);
207 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
212 for(int i
= 0; i
< MaxSize
; ++i
){
213 auxBoostString
= string_literals
<CharType
>::String();
214 auxStdString
= string_literals
<CharType
>::String();
215 string_literals
<CharType
>::sprintf_number(buffer
, i
);
216 auxBoostString
+= buffer
;
217 auxStdString
+= buffer
;
218 boostStringVect
->insert(boostStringVect
->begin(), auxBoostString
);
219 stdStringVect
->insert(stdStringVect
->begin(), auxStdString
);
222 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
226 //Now push front moving
227 for(int i
= 0; i
< MaxSize
; ++i
){
228 auxBoostString
= string_literals
<CharType
>::String();
229 auxStdString
= string_literals
<CharType
>::String();
230 string_literals
<CharType
>::sprintf_number(buffer
, i
);
231 auxBoostString
+= buffer
;
232 auxStdString
+= buffer
;
233 boostStringVect
->insert(boostStringVect
->begin(), boost::move(auxBoostString
));
234 stdStringVect
->insert(stdStringVect
->begin(), auxStdString
);
237 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)){
241 //Now test long and short representation swapping
244 auxBoostString
= string_literals
<CharType
>::String();
245 auxStdString
= string_literals
<CharType
>::String();
246 BoostString boost_swapper
;
247 StdString std_swapper
;
248 boost_swapper
.swap(auxBoostString
);
249 std_swapper
.swap(auxStdString
);
250 if(!StringEqual()(auxBoostString
, auxStdString
))
252 if(!StringEqual()(boost_swapper
, std_swapper
))
254 boost_swapper
.swap(auxBoostString
);
255 std_swapper
.swap(auxStdString
);
256 if(!StringEqual()(auxBoostString
, auxStdString
))
258 if(!StringEqual()(boost_swapper
, std_swapper
))
262 auxBoostString
.shrink_to_fit();
263 StdString(auxStdString
).swap(auxStdString
);
264 if(!StringEqual()(auxBoostString
, auxStdString
))
267 //Reserve + shrink_to_fit
268 auxBoostString
.reserve(boost_swapper
.size()*2+1);
269 auxStdString
.reserve(std_swapper
.size()*2+1);
270 if(!StringEqual()(auxBoostString
, auxStdString
))
273 auxBoostString
.shrink_to_fit();
274 StdString(auxStdString
).swap(auxStdString
);
275 if(!StringEqual()(auxBoostString
, auxStdString
))
279 auxBoostString
= string_literals
<CharType
>::LongString();
280 auxStdString
= string_literals
<CharType
>::LongString();
281 boost_swapper
= BoostString();
282 std_swapper
= StdString();
283 boost_swapper
.swap(auxBoostString
);
284 std_swapper
.swap(auxStdString
);
285 if(!StringEqual()(auxBoostString
, auxStdString
))
287 if(!StringEqual()(boost_swapper
, std_swapper
))
289 boost_swapper
.swap(auxBoostString
);
290 std_swapper
.swap(auxStdString
);
293 auxBoostString
.shrink_to_fit();
294 StdString(auxStdString
).swap(auxStdString
);
295 if(!StringEqual()(auxBoostString
, auxStdString
))
298 auxBoostString
.clear();
299 auxStdString
.clear();
300 auxBoostString
.shrink_to_fit();
301 StdString(auxStdString
).swap(auxStdString
);
302 if(!StringEqual()(auxBoostString
, auxStdString
))
306 std::sort(boostStringVect
->begin(), boostStringVect
->end());
307 std::sort(stdStringVect
->begin(), stdStringVect
->end());
308 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
310 const CharType
*prefix
= string_literals
<CharType
>::Prefix();
311 const int prefix_size
= std::char_traits
<CharType
>::length(prefix
);
312 const CharType
*sufix
= string_literals
<CharType
>::Suffix();
314 for(int i
= 0; i
< MaxSize
; ++i
){
315 (*boostStringVect
)[i
].append(sufix
);
316 (*stdStringVect
)[i
].append(sufix
);
317 (*boostStringVect
)[i
].insert((*boostStringVect
)[i
].begin(),
318 prefix
, prefix
+ prefix_size
);
319 (*stdStringVect
)[i
].insert((*stdStringVect
)[i
].begin(),
320 prefix
, prefix
+ prefix_size
);
323 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
325 for(int i
= 0; i
< MaxSize
; ++i
){
326 std::reverse((*boostStringVect
)[i
].begin(), (*boostStringVect
)[i
].end());
327 std::reverse((*stdStringVect
)[i
].begin(), (*stdStringVect
)[i
].end());
330 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
332 for(int i
= 0; i
< MaxSize
; ++i
){
333 std::reverse((*boostStringVect
)[i
].begin(), (*boostStringVect
)[i
].end());
334 std::reverse((*stdStringVect
)[i
].begin(), (*stdStringVect
)[i
].end());
337 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
339 for(int i
= 0; i
< MaxSize
; ++i
){
340 std::sort(boostStringVect
->begin(), boostStringVect
->end());
341 std::sort(stdStringVect
->begin(), stdStringVect
->end());
344 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
346 for(int i
= 0; i
< MaxSize
; ++i
){
347 (*boostStringVect
)[i
].replace((*boostStringVect
)[i
].begin(),
348 (*boostStringVect
)[i
].end(),
349 string_literals
<CharType
>::String());
350 (*stdStringVect
)[i
].replace((*stdStringVect
)[i
].begin(),
351 (*stdStringVect
)[i
].end(),
352 string_literals
<CharType
>::String());
355 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
357 boostStringVect
->erase(::unique(boostStringVect
->begin(), boostStringVect
->end()),
358 boostStringVect
->end());
359 stdStringVect
->erase(::unique(stdStringVect
->begin(), stdStringVect
->end()),
360 stdStringVect
->end());
361 if(!CheckEqualStringVector(boostStringVect
, stdStringVect
)) return 1;
365 BoostString bs2
= string_literals
<CharType
>::String();
366 StdString ss2
= string_literals
<CharType
>::String();
367 BoostString bs3
= string_literals
<CharType
>::Suffix();
368 StdString ss3
= string_literals
<CharType
>::Suffix();
369 BoostString bs4
= bs2
+ bs3
;
370 StdString ss4
= ss2
+ ss3
;
371 if(!StringEqual()(bs4
, ss4
)){
375 bs4
= bs2
+ BoostString();
376 ss4
= ss2
+ StdString();
377 if(!StringEqual()(bs4
, ss4
)){
381 bs4
= BoostString() + bs2
;
382 ss4
= StdString() + ss2
;
383 if(!StringEqual()(bs4
, ss4
)){
387 bs4
= BoostString() + boost::move(bs2
);
388 ss4
= StdString() + boost::move(ss2
);
389 if(!StringEqual()(bs4
, ss4
)){
393 bs2
= string_literals
<CharType
>::String();
394 ss2
= string_literals
<CharType
>::String();
395 bs4
= boost::move(bs2
) + BoostString();
396 ss4
= boost::move(ss2
) + StdString();
397 if(!StringEqual()(bs4
, ss4
)){
401 bs2
= string_literals
<CharType
>::String();
402 ss2
= string_literals
<CharType
>::String();
403 bs4
= string_literals
<CharType
>::Prefix() + boost::move(bs2
);
404 ss4
= string_literals
<CharType
>::Prefix() + boost::move(ss2
);
405 if(!StringEqual()(bs4
, ss4
)){
409 bs2
= string_literals
<CharType
>::String();
410 ss2
= string_literals
<CharType
>::String();
411 bs4
= boost::move(bs2
) + string_literals
<CharType
>::Suffix();
412 ss4
= boost::move(ss2
) + string_literals
<CharType
>::Suffix();
413 if(!StringEqual()(bs4
, ss4
)){
417 bs2
= string_literals
<CharType
>::String();
418 ss2
= string_literals
<CharType
>::String();
419 bs4
= string_literals
<CharType
>::Prefix() + bs2
;
420 ss4
= string_literals
<CharType
>::Prefix() + ss2
;
421 if(!StringEqual()(bs4
, ss4
)){
425 bs2
= string_literals
<CharType
>::String();
426 ss2
= string_literals
<CharType
>::String();
427 bs4
= bs2
+ string_literals
<CharType
>::Suffix();
428 ss4
= ss2
+ string_literals
<CharType
>::Suffix();
429 if(!StringEqual()(bs4
, ss4
)){
433 bs2
= string_literals
<CharType
>::String();
434 ss2
= string_literals
<CharType
>::String();
435 bs4
= string_literals
<CharType
>::Char() + bs2
;
436 ss4
= string_literals
<CharType
>::Char() + ss2
;
437 if(!StringEqual()(bs4
, ss4
)){
441 bs2
= string_literals
<CharType
>::String();
442 ss2
= string_literals
<CharType
>::String();
443 bs4
= bs2
+ string_literals
<CharType
>::Char();
444 ss4
= ss2
+ string_literals
<CharType
>::Char();
445 if(!StringEqual()(bs4
, ss4
)){
449 //Check front/back/begin/end
451 if(bs4
.front() != *ss4
.begin())
454 if(bs4
.back() != *(ss4
.end()-1))
458 ss4
.erase(ss4
.end()-1);
459 if(!StringEqual()(bs4
, ss4
)){
463 if(*bs4
.begin() != *ss4
.begin())
465 if(*bs4
.cbegin() != *ss4
.begin())
467 if(*bs4
.rbegin() != *ss4
.rbegin())
469 if(*bs4
.crbegin() != *ss4
.rbegin())
471 if(*(bs4
.end()-1) != *(ss4
.end()-1))
473 if(*(bs4
.cend()-1) != *(ss4
.end()-1))
475 if(*(bs4
.rend()-1) != *(ss4
.rend()-1))
477 if(*(bs4
.crend()-1) != *(ss4
.rend()-1))
481 //When done, delete vector
482 delete boostStringVect
;
483 delete stdStringVect
;
488 bool test_expand_bwd()
490 //Now test all back insertion possibilities
491 typedef test::expand_bwd_test_allocator
<char>
493 typedef basic_string
<char, std::char_traits
<char>, allocator_type
>
495 return test::test_all_expand_bwd
<string_type
>();
498 struct boost_container_string
;
500 namespace boost
{ namespace container
{ namespace test
{
503 struct alloc_propagate_base
<boost_container_string
>
505 template <class T
, class Allocator
>
508 typedef boost::container::basic_string
<T
, std::char_traits
<T
>, Allocator
> type
;
513 }}} //namespace boost::container::test
518 if(string_test
<char>()){
522 if(string_test
<wchar_t>()){
526 ////////////////////////////////////
527 // Backwards expansion test
528 ////////////////////////////////////
529 if(!test_expand_bwd())
532 ////////////////////////////////////
533 // Allocator propagation testing
534 ////////////////////////////////////
535 if(!boost::container::test::test_propagate_allocator
<boost_container_string
>())
538 ////////////////////////////////////
540 ////////////////////////////////////
541 if(!test::default_init_test
< basic_string
<char, std::char_traits
<char>, test::default_init_allocator
<char> > >()){
542 std::cerr
<< "Default init test failed" << std::endl
;
546 if(!test::default_init_test
< basic_string
<wchar_t, std::char_traits
<wchar_t>, test::default_init_allocator
<wchar_t> > >()){
547 std::cerr
<< "Default init test failed" << std::endl
;
551 ////////////////////////////////////
553 ////////////////////////////////////
555 typedef boost::container::basic_string
<char> cont_int
;
556 cont_int a
; a
.push_back(char(1)); a
.push_back(char(2)); a
.push_back(char(3));
557 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
560 typedef boost::container::basic_string
<wchar_t> cont_int
;
561 cont_int a
; a
.push_back(wchar_t(1)); a
.push_back(wchar_t(2)); a
.push_back(wchar_t(3));
562 boost::intrusive::test::test_iterator_random
< cont_int
>(a
);
565 ////////////////////////////////////
566 // Comparison testing
567 ////////////////////////////////////
569 if(!boost::container::test::test_container_comparisons
<string
>())
571 if(!boost::container::test::test_container_comparisons
<wstring
>())
575 return boost::report_errors();
578 #include <boost/container/detail/config_end.hpp>