1 //===----------------------------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 // <string>
10 
11 // basic_string(const basic_string& str, const Allocator& alloc);
12 
13 #include <string>
14 #include <cassert>
15 
16 #include "test_macros.h"
17 #include "test_allocator.h"
18 #include "min_allocator.h"
19 
20 #ifndef TEST_HAS_NO_EXCEPTIONS
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> *imp_) : imp (imp_) {}
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 template <class S>
69 void test_assign(S &s1, const S& s2)
70 {
71     try { s1 = s2; }
72     catch ( std::bad_alloc &) { return; }
73     assert(false);
74 }
75 #endif
76 
77 
78 
79 template <class S>
80 void
81 test(S s1, const typename S::allocator_type& a)
82 {
83     S s2(s1, a);
84     LIBCPP_ASSERT(s2.__invariants());
85     assert(s2 == s1);
86     assert(s2.capacity() >= s2.size());
87     assert(s2.get_allocator() == a);
88 }
89 
90 int main(int, char**)
91 {
92     {
93     typedef test_allocator<char> A;
94     typedef std::basic_string<char, std::char_traits<char>, A> S;
95     test(S(), A(3));
96     test(S("1"), A(5));
97     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A(7));
98     }
99 #if TEST_STD_VER >= 11
100     {
101     typedef min_allocator<char> A;
102     typedef std::basic_string<char, std::char_traits<char>, A> S;
103     test(S(), A());
104     test(S("1"), A());
105     test(S("1234567890123456789012345678901234567890123456789012345678901234567890"), A());
106     }
107 
108 #ifndef TEST_HAS_NO_EXCEPTIONS
109     {
110     typedef poca_alloc<char> A;
111     typedef std::basic_string<char, std::char_traits<char>, A> S;
112     const char * p1 = "This is my first string";
113     const char * p2 = "This is my second string";
114 
115     alloc_imp<char> imp1;
116     alloc_imp<char> imp2;
117     S s1(p1, A(&imp1));
118     S s2(p2, A(&imp2));
119 
120     assert(s1 == p1);
121     assert(s2 == p2);
122 
123     imp2.deactivate();
124     test_assign(s1, s2);
125     assert(s1 == p1);
126     assert(s2 == p2);
127     }
128 #endif
129 #endif
130 
131   return 0;
132 }
133