1 //===----------------------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is dual licensed under the MIT and the University of Illinois Open
6 // Source Licenses. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 // <string>
11 
12 // basic_string(const basic_string& str, const Allocator& alloc);
13 
14 #include <string>
15 #include <cassert>
16 
17 #include "test_macros.h"
18 #include "test_allocator.h"
19 #include "min_allocator.h"
20 
21 template <class T>
22 struct alloc_imp {
23     bool active;
24 
25     alloc_imp() : active(true) {}
26 
27     T* allocate(std::size_t n)
28     {
29         if (active)
30             return static_cast<T*>(std::malloc(n * sizeof(T)));
31         else
32             throw std::bad_alloc();
33     }
34 
35     void deallocate(T* p, std::size_t) { std::free(p); }
36     void activate  ()                  { active = true; }
37     void deactivate()                  { active = false; }
38 };
39 
40 template <class T>
41 struct poca_alloc {
42     typedef T value_type;
43     typedef std::true_type propagate_on_container_copy_assignment;
44 
45     alloc_imp<T> *imp;
46 
47     poca_alloc(alloc_imp<T> *ximp) : imp (ximp) {}
48 
49     template <class U>
50     poca_alloc(const poca_alloc<U>& other) : imp(other.imp) {}
51 
52     T*   allocate  (std::size_t n)       { return imp->allocate(n);}
53     void deallocate(T* p, std::size_t n) { imp->deallocate(p, n); }
54 };
55 
56 template <typename T, typename U>
57 bool operator==(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs)
58 {
59     return lhs.imp == rhs.imp;
60 }
61 
62 template <typename T, typename U>
63 bool operator!=(const poca_alloc<T>& lhs, const poca_alloc<U>& rhs)
64 {
65     return lhs.imp != rhs.imp;
66 }
67 
68 
69 
70 template <class S>
71 void
72 test(S s1, const typename S::allocator_type& a)
73 {
74     S s2(s1, a);
75     LIBCPP_ASSERT(s2.__invariants());
76     assert(s2 == s1);
77     assert(s2.capacity() >= s2.size());
78     assert(s2.get_allocator() == a);
79 }
80 
81 #ifndef TEST_HAS_NO_EXCEPTIONS
82 template <class S>
83 void test_assign(S &s1, const S& s2)
84 {
85 	try { s1 = s2; }
86 	catch ( std::bad_alloc &) { return; }
87 	assert(false);
88 }
89 #endif
90 
91 int main()
92 {
93     {
94     typedef test_allocator<char> A;
95     typedef std::basic_string<char, std::char_traits<char>, A> S;
96     test(S(), A(3));
97     test(S("1"), A(5));
98     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
99     }
100 #if TEST_STD_VER >= 11
101     {
102     typedef min_allocator<char> A;
103     typedef std::basic_string<char, std::char_traits<char>, A> S;
104     test(S(), A());
105     test(S("1"), A());
106     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
107     }
108 
109 #ifndef TEST_HAS_NO_EXCEPTIONS
110     {
111     typedef poca_alloc<char> A;
112     typedef std::basic_string<char, std::char_traits<char>, A> S;
113 	const char * p1 = "This is my first string";
114 	const char * p2 = "This is my second string";
115 
116     alloc_imp<char> imp1;
117     alloc_imp<char> imp2;
118 	S s1(p1, A(&imp1));
119 	S s2(p2, A(&imp2));
120 
121 	assert(s1 == p1);
122 	assert(s2 == p2);
123 
124 	imp2.deactivate();
125 	test_assign(s1, s2);
126 	assert(s1 == p1);
127 	assert(s2 == p2);
128     }
129 #endif
130 #endif
131 }
132