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 // UNSUPPORTED: c++03, c++11, c++14
10 // UNSUPPORTED: availability-filesystem-missing
11 
12 // These tests require locale for non-char paths
13 // UNSUPPORTED: no-localization
14 
15 // <filesystem>
16 
17 // class path
18 
19 // template <class ECharT, class Traits = char_traits<ECharT>,
20 //           class Allocator = allocator<ECharT>>
21 // basic_string<ECharT, Traits, Allocator>
22 // string(const Allocator& a = Allocator()) const;
23 
24 #include <filesystem>
25 #include <type_traits>
26 #include <cassert>
27 
28 #include "count_new.h"
29 #include "make_string.h"
30 #include "min_allocator.h"
31 #include "test_iterators.h"
32 #include "test_macros.h"
33 namespace fs = std::filesystem;
34 
35 // the SSO is always triggered for strings of size 2.
36 MultiStringType shortString = MKSTR("a");
37 MultiStringType longString = MKSTR("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ/123456789/abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
38 
39 template <class CharT>
doShortStringTest(MultiStringType const & MS)40 void doShortStringTest(MultiStringType const& MS) {
41   using namespace fs;
42   using Ptr = CharT const*;
43   using Str = std::basic_string<CharT>;
44   using Alloc = std::allocator<CharT>;
45   Ptr value = MS;
46   const path p((const char*)MS);
47 #ifdef _WIN32
48   // On Windows, charset conversions cause allocations outside of the
49   // provided allocator, but accessing the native type should work without
50   // extra allocations.
51   bool DisableAllocations = std::is_same<CharT, path::value_type>::value;
52 #else
53   // On other platforms, these methods only use the provided allocator, and
54   // no extra allocations should be done.
55   bool DisableAllocations = true;
56 #endif
57   {
58       DisableAllocationGuard g(DisableAllocations);
59       Str s = p.string<CharT>();
60       assert(s == value);
61       Str s2 = p.string<CharT>(Alloc{});
62       assert(s2 == value);
63   }
64   using MAlloc = malloc_allocator<CharT>;
65   MAlloc::reset();
66   {
67       using Traits = std::char_traits<CharT>;
68       using AStr = std::basic_string<CharT, Traits, MAlloc>;
69       DisableAllocationGuard g(DisableAllocations);
70       AStr s = p.string<CharT, Traits, MAlloc>();
71       assert(s == value);
72       assert(MAlloc::alloc_count == 0);
73       assert(MAlloc::outstanding_alloc() == 0);
74   }
75   MAlloc::reset();
76   { // Other allocator - provided copy
77       using Traits = std::char_traits<CharT>;
78       using AStr = std::basic_string<CharT, Traits, MAlloc>;
79       DisableAllocationGuard g(DisableAllocations);
80       MAlloc a;
81       // don't allow another allocator to be default constructed.
82       MAlloc::disable_default_constructor = true;
83       AStr s = p.string<CharT, Traits, MAlloc>(a);
84       assert(s == value);
85       assert(MAlloc::alloc_count == 0);
86       assert(MAlloc::outstanding_alloc() == 0);
87   }
88   MAlloc::reset();
89 }
90 
91 template <class CharT>
doLongStringTest(MultiStringType const & MS)92 void doLongStringTest(MultiStringType const& MS) {
93   using namespace fs;
94   using Ptr = CharT const*;
95   using Str = std::basic_string<CharT>;
96   Ptr value = MS;
97   const path p((const char*)MS);
98   { // Default allocator
99       using Alloc = std::allocator<CharT>;
100       Str s = p.string<CharT>();
101       assert(s == value);
102       Str s2 = p.string<CharT>(Alloc{});
103       assert(s2 == value);
104   }
105   using MAlloc = malloc_allocator<CharT>;
106   MAlloc::reset();
107 #ifdef _WIN32
108   // On Windows, charset conversions cause allocations outside of the
109   // provided allocator, but accessing the native type should work without
110   // extra allocations.
111   bool DisableAllocations = std::is_same<CharT, path::value_type>::value;
112 #else
113   // On other platforms, these methods only use the provided allocator, and
114   // no extra allocations should be done.
115   bool DisableAllocations = true;
116 #endif
117 
118   { // Other allocator - default construct
119       using Traits = std::char_traits<CharT>;
120       using AStr = std::basic_string<CharT, Traits, MAlloc>;
121       DisableAllocationGuard g(DisableAllocations);
122       AStr s = p.string<CharT, Traits, MAlloc>();
123       assert(s == value);
124       assert(MAlloc::alloc_count > 0);
125       assert(MAlloc::outstanding_alloc() == 1);
126   }
127   MAlloc::reset();
128   { // Other allocator - provided copy
129       using Traits = std::char_traits<CharT>;
130       using AStr = std::basic_string<CharT, Traits, MAlloc>;
131       DisableAllocationGuard g(DisableAllocations);
132       MAlloc a;
133       // don't allow another allocator to be default constructed.
134       MAlloc::disable_default_constructor = true;
135       AStr s = p.string<CharT, Traits, MAlloc>(a);
136       assert(s == value);
137       assert(MAlloc::alloc_count > 0);
138       assert(MAlloc::outstanding_alloc() == 1);
139   }
140   MAlloc::reset();
141   /////////////////////////////////////////////////////////////////////////////
142 }
143 
main(int,char **)144 int main(int, char**)
145 {
146   using namespace fs;
147   {
148     auto const& S = shortString;
149     doShortStringTest<char>(S);
150 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
151     doShortStringTest<wchar_t>(S);
152 #endif
153     doShortStringTest<char16_t>(S);
154     doShortStringTest<char32_t>(S);
155 #if TEST_STD_VER > 17 && defined(__cpp_lib_char8_t)
156     doShortStringTest<char8_t>(S);
157 #endif
158   }
159   {
160     auto const& S = longString;
161     doLongStringTest<char>(S);
162 #ifndef TEST_HAS_NO_WIDE_CHARACTERS
163     doLongStringTest<wchar_t>(S);
164 #endif
165     doLongStringTest<char16_t>(S);
166     doLongStringTest<char32_t>(S);
167 #if TEST_STD_VER > 17 && defined(__cpp_lib_char8_t)
168     doLongStringTest<char8_t>(S);
169 #endif
170   }
171 
172   return 0;
173 }
174