1 //
2 // Copyright (c) 2012 Artyom Beilis (Tonkikh)
3 // Copyright (c) 2019-2020 Alexander Grund
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //
9
10 #include <boost/nowide/stackstring.hpp>
11 #include <iostream>
12 #include <vector>
13
14 #include "test.hpp"
15 #include "test_sets.hpp"
16
17 #if defined(BOOST_MSVC) && BOOST_MSVC < 1700
18 #pragma warning(disable : 4428) // universal-character-name encountered in source
19 #endif
20
21 template<typename CharOut, typename CharIn, size_t BufferSize>
22 class test_basic_stackstring : public boost::nowide::basic_stackstring<CharOut, CharIn, BufferSize>
23 {
24 public:
25 typedef boost::nowide::basic_stackstring<CharOut, CharIn, BufferSize> parent;
26
27 using parent::parent;
28 using parent::uses_stack_memory;
uses_heap_memory() const29 bool uses_heap_memory() const
30 {
31 return !uses_stack_memory() && this->get();
32 }
33 };
34
35 typedef test_basic_stackstring<wchar_t, char, 256> test_wstackstring;
36 typedef test_basic_stackstring<char, wchar_t, 256> test_stackstring;
37
stackstring_to_wide(const std::string & s)38 std::wstring stackstring_to_wide(const std::string& s)
39 {
40 const test_wstackstring ss(s.c_str());
41 TEST(ss.uses_stack_memory());
42 return ss.get();
43 }
44
stackstring_to_narrow(const std::wstring & s)45 std::string stackstring_to_narrow(const std::wstring& s)
46 {
47 const test_stackstring ss(s.c_str());
48 TEST(ss.uses_stack_memory());
49 return ss.get();
50 }
51
heap_stackstring_to_wide(const std::string & s)52 std::wstring heap_stackstring_to_wide(const std::string& s)
53 {
54 const test_basic_stackstring<wchar_t, char, 1> ss(s.c_str());
55 TEST(ss.uses_heap_memory() || s.empty());
56 return ss.get();
57 }
58
heap_stackstring_to_narrow(const std::wstring & s)59 std::string heap_stackstring_to_narrow(const std::wstring& s)
60 {
61 const test_basic_stackstring<char, wchar_t, 1> ss(s.c_str());
62 TEST(ss.uses_heap_memory() || s.empty());
63 return ss.get();
64 }
65
test_main(int,char **,char **)66 void test_main(int, char**, char**)
67 {
68 std::string hello = "\xd7\xa9\xd7\x9c\xd7\x95\xd7\x9d";
69 std::wstring whello = boost::nowide::widen(hello);
70 const wchar_t* wempty = L"";
71
72 {
73 std::cout << "-- Default constructed string is NULL" << std::endl;
74 const boost::nowide::short_stackstring s;
75 TEST(s.get() == NULL);
76 }
77 {
78 std::cout << "-- NULL ptr passed to ctor results in NULL" << std::endl;
79 const boost::nowide::short_stackstring s(NULL);
80 TEST(s.get() == NULL);
81 const boost::nowide::short_stackstring s2(NULL, NULL);
82 TEST(s2.get() == NULL);
83 }
84 {
85 std::cout << "-- NULL ptr passed to convert results in NULL" << std::endl;
86 boost::nowide::short_stackstring s(L"foo");
87 TEST(s.get() == std::string("foo"));
88 s.convert(NULL);
89 TEST(s.get() == NULL);
90 boost::nowide::short_stackstring s2(L"foo");
91 TEST(s2.get() == std::string("foo"));
92 s2.convert(NULL, NULL);
93 TEST(s2.get() == NULL);
94 }
95 {
96 std::cout << "-- An empty string is accepted" << std::endl;
97 const boost::nowide::short_stackstring s(wempty);
98 TEST(s.get());
99 TEST(s.get() == std::string());
100 const boost::nowide::short_stackstring s2(wempty, wempty);
101 TEST(s2.get());
102 TEST(s2.get() == std::string());
103 }
104 {
105 std::cout << "-- An empty string is accepted" << std::endl;
106 boost::nowide::short_stackstring s, s2;
107 TEST(s.convert(wempty));
108 TEST(s.get() == std::string());
109 TEST(s2.convert(wempty, wempty));
110 TEST(s2.get() == std::string());
111 }
112 {
113 std::cout << "-- Will be put on heap" << std::endl;
114 test_basic_stackstring<wchar_t, char, 3> sw;
115 TEST(sw.convert(hello.c_str()));
116 TEST(sw.uses_heap_memory());
117 TEST(sw.get() == whello);
118 TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
119 TEST(sw.uses_heap_memory());
120 TEST(sw.get() == whello);
121 }
122 {
123 std::cout << "-- Will be put on stack" << std::endl;
124 test_basic_stackstring<wchar_t, char, 40> sw;
125 TEST(sw.convert(hello.c_str()));
126 TEST(sw.uses_stack_memory());
127 TEST(sw.get() == whello);
128 TEST(sw.convert(hello.c_str(), hello.c_str() + hello.size()));
129 TEST(sw.uses_stack_memory());
130 TEST(sw.get() == whello);
131 }
132 {
133 std::cout << "-- Will be put on heap" << std::endl;
134 test_basic_stackstring<char, wchar_t, 3> sw;
135 TEST(sw.convert(whello.c_str()));
136 TEST(sw.uses_heap_memory());
137 TEST(sw.get() == hello);
138 TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
139 TEST(sw.uses_heap_memory());
140 TEST(sw.get() == hello);
141 }
142 {
143 std::cout << "-- Will be put on stack" << std::endl;
144 test_basic_stackstring<char, wchar_t, 40> sw;
145 TEST(sw.convert(whello.c_str()));
146 TEST(sw.uses_stack_memory());
147 TEST(sw.get() == hello);
148 TEST(sw.convert(whello.c_str(), whello.c_str() + whello.size()));
149 TEST(sw.uses_stack_memory());
150 TEST(sw.get() == hello);
151 }
152 {
153 typedef test_basic_stackstring<wchar_t, char, 6> stackstring;
154 const std::wstring heapVal = L"heapValue";
155 const std::wstring stackVal = L"stack";
156 const stackstring heap(boost::nowide::narrow(heapVal).c_str());
157 const stackstring stack(boost::nowide::narrow(stackVal).c_str());
158 TEST(heap.uses_heap_memory());
159 TEST(stack.uses_stack_memory());
160
161 {
162 stackstring sw2(heap), sw3, sEmpty;
163 sw3 = heap;
164 TEST(sw2.get() == heapVal);
165 TEST(sw3.get() == heapVal);
166 // Self assign avoiding clang self-assign-overloaded warning
167 sw3 = static_cast<const stackstring&>(sw3); //-V570
168 TEST(sw3.get() == heapVal);
169 // Assign empty
170 sw3 = sEmpty; //-V820
171 TEST(sw3.get() == NULL);
172 }
173 {
174 stackstring sw2(stack), sw3, sEmpty;
175 sw3 = stack;
176 TEST(sw2.get() == stackVal);
177 TEST(sw3.get() == stackVal);
178 // Self assign avoiding clang self-assign-overloaded warning
179 sw3 = static_cast<const stackstring&>(sw3); //-V570
180 TEST(sw3.get() == stackVal);
181 // Assign empty
182 sw3 = sEmpty; //-V820
183 TEST(sw3.get() == NULL);
184 }
185 {
186 stackstring sw2(stack);
187 sw2 = heap;
188 TEST(sw2.get() == heapVal);
189 }
190 {
191 stackstring sw2(heap);
192 sw2 = stack;
193 TEST(sw2.get() == stackVal);
194 }
195 {
196 stackstring sw2(heap), sw3(stack), sEmpty1, sEmpty2;
197 swap(sw2, sw3);
198 TEST(sw2.get() == stackVal);
199 TEST(sw3.get() == heapVal);
200 swap(sw2, sw3);
201 TEST(sw2.get() == heapVal);
202 TEST(sw3.get() == stackVal);
203 swap(sw2, sEmpty1);
204 TEST(sEmpty1.get() == heapVal);
205 TEST(sw2.get() == NULL);
206 swap(sw3, sEmpty2);
207 TEST(sEmpty2.get() == stackVal);
208 TEST(sw3.get() == NULL);
209 }
210 {
211 stackstring sw2(heap), sw3(heap);
212 sw3.get()[0] = 'z';
213 const std::wstring val2 = sw3.get();
214 swap(sw2, sw3);
215 TEST(sw2.get() == val2);
216 TEST(sw3.get() == heapVal);
217 }
218 {
219 stackstring sw2(stack), sw3(stack);
220 sw3.get()[0] = 'z';
221 const std::wstring val2 = sw3.get();
222 swap(sw2, sw3);
223 TEST(sw2.get() == val2);
224 TEST(sw3.get() == stackVal);
225 }
226 std::cout << "-- Sanity check" << std::endl;
227 TEST(stack.get() == stackVal);
228 TEST(heap.get() == heapVal);
229 }
230 {
231 std::cout << "-- Test putting stackstrings into vector (done by args) class" << std::endl;
232 // Use a smallish buffer, to have stack and heap values
233 typedef boost::nowide::basic_stackstring<wchar_t, char, 5> stackstring;
234 std::vector<stackstring> strings;
235 strings.resize(2);
236 TEST(strings[0].convert("1234") == std::wstring(L"1234"));
237 TEST(strings[1].convert("Hello World") == std::wstring(L"Hello World"));
238 strings.push_back(stackstring("FooBar"));
239 TEST(strings[0].get() == std::wstring(L"1234"));
240 TEST(strings[1].get() == std::wstring(L"Hello World"));
241 TEST(strings[2].get() == std::wstring(L"FooBar"));
242 }
243 std::cout << "- Stackstring" << std::endl;
244 run_all(stackstring_to_wide, stackstring_to_narrow);
245 std::cout << "- Heap Stackstring" << std::endl;
246 run_all(heap_stackstring_to_wide, heap_stackstring_to_narrow);
247 }
248