Mercurial > hg > CbC > CbC_llvm
comparison libcxx/src/string.cpp @ 236:c4bab56944e8 llvm-original
LLVM 16
author | kono |
---|---|
date | Wed, 09 Nov 2022 17:45:10 +0900 |
parents | 5f17cb93ff66 |
children | 1f2b6ac9f198 |
comparison
equal
deleted
inserted
replaced
232:70dce7da266c | 236:c4bab56944e8 |
---|---|
1 //===------------------------- string.cpp ---------------------------------===// | 1 //===----------------------------------------------------------------------===// |
2 // | 2 // |
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 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. | 4 // See https://llvm.org/LICENSE.txt for license information. |
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 // | 6 // |
7 //===----------------------------------------------------------------------===// | 7 //===----------------------------------------------------------------------===// |
8 | 8 |
9 #include "string" | 9 #include <__assert> |
10 #include "charconv" | 10 #include <cerrno> |
11 #include "cstdlib" | 11 #include <charconv> |
12 #include "cwchar" | 12 #include <cstdlib> |
13 #include "cerrno" | 13 #include <limits> |
14 #include "limits" | 14 #include <stdexcept> |
15 #include "stdexcept" | |
16 #include <stdio.h> | 15 #include <stdio.h> |
17 #include "__debug" | 16 #include <string> |
17 | |
18 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS | |
19 # include <cwchar> | |
20 #endif | |
18 | 21 |
19 _LIBCPP_BEGIN_NAMESPACE_STD | 22 _LIBCPP_BEGIN_NAMESPACE_STD |
20 | 23 |
21 template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>; | 24 #ifndef _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON |
25 | |
26 template <bool> | |
27 struct __basic_string_common; | |
28 | |
29 // The struct isn't declared anymore in the headers. It's only here for ABI compatibility. | |
30 template <> | |
31 struct __basic_string_common<true> { | |
32 _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_length_error() const; | |
33 _LIBCPP_NORETURN _LIBCPP_EXPORTED_FROM_ABI void __throw_out_of_range() const; | |
34 }; | |
35 | |
36 void __basic_string_common<true>::__throw_length_error() const { | |
37 std::__throw_length_error("basic_string"); | |
38 } | |
39 void __basic_string_common<true>::__throw_out_of_range() const { | |
40 std::__throw_out_of_range("basic_string"); | |
41 } | |
42 | |
43 #endif // _LIBCPP_ABI_DO_NOT_EXPORT_BASIC_STRING_COMMON | |
22 | 44 |
23 #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; | 45 #define _LIBCPP_EXTERN_TEMPLATE_DEFINE(...) template __VA_ARGS__; |
24 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION | 46 #ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATION |
25 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) | 47 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) |
26 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) | 48 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
49 _LIBCPP_STRING_UNSTABLE_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) | |
50 # endif | |
27 #else | 51 #else |
28 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) | 52 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) |
29 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) | 53 # ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
54 _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) | |
55 # endif | |
30 #endif | 56 #endif |
31 #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE | 57 #undef _LIBCPP_EXTERN_TEMPLATE_DEFINE |
32 | 58 |
33 template string operator+<char, char_traits<char>, allocator<char> >(char const*, string const&); | 59 template string operator+<char, char_traits<char>, allocator<char>>(char const*, string const&); |
34 | 60 |
35 namespace | 61 namespace |
36 { | 62 { |
37 | 63 |
38 template<typename T> | 64 template<typename T> |
39 inline | 65 inline void throw_helper(const string& msg) { |
40 void throw_helper( const string& msg ) | |
41 { | |
42 #ifndef _LIBCPP_NO_EXCEPTIONS | 66 #ifndef _LIBCPP_NO_EXCEPTIONS |
43 throw T( msg ); | 67 throw T(msg); |
44 #else | 68 #else |
45 fprintf(stderr, "%s\n", msg.c_str()); | 69 fprintf(stderr, "%s\n", msg.c_str()); |
46 _VSTD::abort(); | 70 _VSTD::abort(); |
47 #endif | 71 #endif |
48 } | 72 } |
49 | 73 |
50 inline | 74 inline void throw_from_string_out_of_range(const string& func) { |
51 void throw_from_string_out_of_range( const string& func ) | |
52 { | |
53 throw_helper<out_of_range>(func + ": out of range"); | 75 throw_helper<out_of_range>(func + ": out of range"); |
54 } | 76 } |
55 | 77 |
56 inline | 78 inline void throw_from_string_invalid_arg(const string& func) { |
57 void throw_from_string_invalid_arg( const string& func ) | |
58 { | |
59 throw_helper<invalid_argument>(func + ": no conversion"); | 79 throw_helper<invalid_argument>(func + ": no conversion"); |
60 } | 80 } |
61 | 81 |
62 // as_integer | 82 // as_integer |
63 | 83 |
64 template<typename V, typename S, typename F> | 84 template<typename V, typename S, typename F> |
65 inline | 85 inline V as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) { |
66 V | |
67 as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f) | |
68 { | |
69 typename S::value_type* ptr = nullptr; | 86 typename S::value_type* ptr = nullptr; |
70 const typename S::value_type* const p = str.c_str(); | 87 const typename S::value_type* const p = str.c_str(); |
71 typename remove_reference<decltype(errno)>::type errno_save = errno; | 88 __libcpp_remove_reference_t<decltype(errno)> errno_save = errno; |
72 errno = 0; | 89 errno = 0; |
73 V r = f(p, &ptr, base); | 90 V r = f(p, &ptr, base); |
74 swap(errno, errno_save); | 91 swap(errno, errno_save); |
75 if (errno_save == ERANGE) | 92 if (errno_save == ERANGE) |
76 throw_from_string_out_of_range(func); | 93 throw_from_string_out_of_range(func); |
80 *idx = static_cast<size_t>(ptr - p); | 97 *idx = static_cast<size_t>(ptr - p); |
81 return r; | 98 return r; |
82 } | 99 } |
83 | 100 |
84 template<typename V, typename S> | 101 template<typename V, typename S> |
85 inline | 102 inline V as_integer(const string& func, const S& s, size_t* idx, int base); |
86 V | |
87 as_integer(const string& func, const S& s, size_t* idx, int base); | |
88 | 103 |
89 // string | 104 // string |
90 template<> | 105 template<> |
91 inline | 106 inline int as_integer(const string& func, const string& s, size_t* idx, int base) { |
92 int | |
93 as_integer(const string& func, const string& s, size_t* idx, int base ) | |
94 { | |
95 // Use long as no Standard string to integer exists. | 107 // Use long as no Standard string to integer exists. |
96 long r = as_integer_helper<long>( func, s, idx, base, strtol ); | 108 long r = as_integer_helper<long>(func, s, idx, base, strtol); |
97 if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) | 109 if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) |
98 throw_from_string_out_of_range(func); | 110 throw_from_string_out_of_range(func); |
99 return static_cast<int>(r); | 111 return static_cast<int>(r); |
100 } | 112 } |
101 | 113 |
102 template<> | 114 template<> |
103 inline | 115 inline long as_integer(const string& func, const string& s, size_t* idx, int base) { |
104 long | 116 return as_integer_helper<long>(func, s, idx, base, strtol); |
105 as_integer(const string& func, const string& s, size_t* idx, int base ) | 117 } |
106 { | 118 |
107 return as_integer_helper<long>( func, s, idx, base, strtol ); | 119 template<> |
108 } | 120 inline unsigned long as_integer(const string& func, const string& s, size_t* idx, int base) { |
109 | 121 return as_integer_helper<unsigned long>(func, s, idx, base, strtoul); |
110 template<> | 122 } |
111 inline | 123 |
112 unsigned long | 124 template<> |
113 as_integer( const string& func, const string& s, size_t* idx, int base ) | 125 inline long long as_integer(const string& func, const string& s, size_t* idx, int base) { |
114 { | 126 return as_integer_helper<long long>(func, s, idx, base, strtoll); |
115 return as_integer_helper<unsigned long>( func, s, idx, base, strtoul ); | 127 } |
116 } | 128 |
117 | 129 template<> |
118 template<> | 130 inline unsigned long long as_integer(const string& func, const string& s, size_t* idx, int base) { |
119 inline | 131 return as_integer_helper<unsigned long long>(func, s, idx, base, strtoull); |
120 long long | 132 } |
121 as_integer( const string& func, const string& s, size_t* idx, int base ) | 133 |
122 { | 134 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
123 return as_integer_helper<long long>( func, s, idx, base, strtoll ); | |
124 } | |
125 | |
126 template<> | |
127 inline | |
128 unsigned long long | |
129 as_integer( const string& func, const string& s, size_t* idx, int base ) | |
130 { | |
131 return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull ); | |
132 } | |
133 | |
134 // wstring | 135 // wstring |
135 template<> | 136 template<> |
136 inline | 137 inline int as_integer(const string& func, const wstring& s, size_t* idx, int base) { |
137 int | |
138 as_integer( const string& func, const wstring& s, size_t* idx, int base ) | |
139 { | |
140 // Use long as no Stantard string to integer exists. | 138 // Use long as no Stantard string to integer exists. |
141 long r = as_integer_helper<long>( func, s, idx, base, wcstol ); | 139 long r = as_integer_helper<long>(func, s, idx, base, wcstol); |
142 if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) | 140 if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r) |
143 throw_from_string_out_of_range(func); | 141 throw_from_string_out_of_range(func); |
144 return static_cast<int>(r); | 142 return static_cast<int>(r); |
145 } | 143 } |
146 | 144 |
147 template<> | 145 template<> |
148 inline | 146 inline long as_integer(const string& func, const wstring& s, size_t* idx, int base) { |
149 long | 147 return as_integer_helper<long>(func, s, idx, base, wcstol); |
150 as_integer( const string& func, const wstring& s, size_t* idx, int base ) | |
151 { | |
152 return as_integer_helper<long>( func, s, idx, base, wcstol ); | |
153 } | 148 } |
154 | 149 |
155 template<> | 150 template<> |
156 inline | 151 inline |
157 unsigned long | 152 unsigned long |
158 as_integer( const string& func, const wstring& s, size_t* idx, int base ) | 153 as_integer(const string& func, const wstring& s, size_t* idx, int base) |
159 { | 154 { |
160 return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul ); | 155 return as_integer_helper<unsigned long>(func, s, idx, base, wcstoul); |
161 } | 156 } |
162 | 157 |
163 template<> | 158 template<> |
164 inline | 159 inline long long as_integer(const string& func, const wstring& s, size_t* idx, int base) { |
165 long long | 160 return as_integer_helper<long long>(func, s, idx, base, wcstoll); |
166 as_integer( const string& func, const wstring& s, size_t* idx, int base ) | 161 } |
167 { | 162 |
168 return as_integer_helper<long long>( func, s, idx, base, wcstoll ); | 163 template<> |
169 } | 164 inline unsigned long long as_integer(const string& func, const wstring& s, size_t* idx, int base) { |
170 | 165 return as_integer_helper<unsigned long long>(func, s, idx, base, wcstoull); |
171 template<> | 166 } |
172 inline | 167 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS |
173 unsigned long long | |
174 as_integer( const string& func, const wstring& s, size_t* idx, int base ) | |
175 { | |
176 return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull ); | |
177 } | |
178 | 168 |
179 // as_float | 169 // as_float |
180 | 170 |
181 template<typename V, typename S, typename F> | 171 template<typename V, typename S, typename F> |
182 inline | 172 inline V as_float_helper(const string& func, const S& str, size_t* idx, F f) { |
183 V | |
184 as_float_helper(const string& func, const S& str, size_t* idx, F f ) | |
185 { | |
186 typename S::value_type* ptr = nullptr; | 173 typename S::value_type* ptr = nullptr; |
187 const typename S::value_type* const p = str.c_str(); | 174 const typename S::value_type* const p = str.c_str(); |
188 typename remove_reference<decltype(errno)>::type errno_save = errno; | 175 __libcpp_remove_reference_t<decltype(errno)> errno_save = errno; |
189 errno = 0; | 176 errno = 0; |
190 V r = f(p, &ptr); | 177 V r = f(p, &ptr); |
191 swap(errno, errno_save); | 178 swap(errno, errno_save); |
192 if (errno_save == ERANGE) | 179 if (errno_save == ERANGE) |
193 throw_from_string_out_of_range(func); | 180 throw_from_string_out_of_range(func); |
197 *idx = static_cast<size_t>(ptr - p); | 184 *idx = static_cast<size_t>(ptr - p); |
198 return r; | 185 return r; |
199 } | 186 } |
200 | 187 |
201 template<typename V, typename S> | 188 template<typename V, typename S> |
202 inline | 189 inline V as_float(const string& func, const S& s, size_t* idx = nullptr); |
203 V as_float( const string& func, const S& s, size_t* idx = nullptr ); | 190 |
204 | 191 template<> |
205 template<> | 192 inline float as_float(const string& func, const string& s, size_t* idx) { |
206 inline | 193 return as_float_helper<float>(func, s, idx, strtof); |
207 float | 194 } |
208 as_float( const string& func, const string& s, size_t* idx ) | 195 |
209 { | 196 template<> |
210 return as_float_helper<float>( func, s, idx, strtof ); | 197 inline double as_float(const string& func, const string& s, size_t* idx) { |
211 } | 198 return as_float_helper<double>(func, s, idx, strtod); |
212 | 199 } |
213 template<> | 200 |
214 inline | 201 template<> |
215 double | 202 inline long double as_float(const string& func, const string& s, size_t* idx) { |
216 as_float(const string& func, const string& s, size_t* idx ) | 203 return as_float_helper<long double>(func, s, idx, strtold); |
217 { | 204 } |
218 return as_float_helper<double>( func, s, idx, strtod ); | 205 |
219 } | 206 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
220 | 207 template<> |
221 template<> | 208 inline float as_float(const string& func, const wstring& s, size_t* idx) { |
222 inline | 209 return as_float_helper<float>(func, s, idx, wcstof); |
223 long double | 210 } |
224 as_float( const string& func, const string& s, size_t* idx ) | 211 |
225 { | 212 template<> |
226 return as_float_helper<long double>( func, s, idx, strtold ); | 213 inline double as_float(const string& func, const wstring& s, size_t* idx) { |
227 } | 214 return as_float_helper<double>(func, s, idx, wcstod); |
228 | 215 } |
229 template<> | 216 |
230 inline | 217 template<> |
231 float | 218 inline long double as_float(const string& func, const wstring& s, size_t* idx) { |
232 as_float( const string& func, const wstring& s, size_t* idx ) | 219 return as_float_helper<long double>(func, s, idx, wcstold); |
233 { | 220 } |
234 return as_float_helper<float>( func, s, idx, wcstof ); | 221 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS |
235 } | |
236 | |
237 template<> | |
238 inline | |
239 double | |
240 as_float( const string& func, const wstring& s, size_t* idx ) | |
241 { | |
242 return as_float_helper<double>( func, s, idx, wcstod ); | |
243 } | |
244 | |
245 template<> | |
246 inline | |
247 long double | |
248 as_float( const string& func, const wstring& s, size_t* idx ) | |
249 { | |
250 return as_float_helper<long double>( func, s, idx, wcstold ); | |
251 } | |
252 | 222 |
253 } // unnamed namespace | 223 } // unnamed namespace |
254 | 224 |
255 int | 225 int stoi(const string& str, size_t* idx, int base) { |
256 stoi(const string& str, size_t* idx, int base) | 226 return as_integer<int>("stoi", str, idx, base); |
257 { | 227 } |
258 return as_integer<int>( "stoi", str, idx, base ); | 228 |
259 } | 229 long stol(const string& str, size_t* idx, int base) { |
260 | 230 return as_integer<long>("stol", str, idx, base); |
261 int | 231 } |
262 stoi(const wstring& str, size_t* idx, int base) | 232 |
263 { | 233 unsigned long stoul(const string& str, size_t* idx, int base) { |
264 return as_integer<int>( "stoi", str, idx, base ); | 234 return as_integer<unsigned long>("stoul", str, idx, base); |
265 } | 235 } |
266 | 236 |
267 long | 237 long long stoll(const string& str, size_t* idx, int base) { |
268 stol(const string& str, size_t* idx, int base) | 238 return as_integer<long long>("stoll", str, idx, base); |
269 { | 239 } |
270 return as_integer<long>( "stol", str, idx, base ); | 240 |
271 } | 241 unsigned long long stoull(const string& str, size_t* idx, int base) { |
272 | 242 return as_integer<unsigned long long>("stoull", str, idx, base); |
273 long | 243 } |
274 stol(const wstring& str, size_t* idx, int base) | 244 |
275 { | 245 float stof(const string& str, size_t* idx) { |
276 return as_integer<long>( "stol", str, idx, base ); | 246 return as_float<float>("stof", str, idx); |
277 } | 247 } |
278 | 248 |
279 unsigned long | 249 double stod(const string& str, size_t* idx) { |
280 stoul(const string& str, size_t* idx, int base) | 250 return as_float<double>("stod", str, idx); |
281 { | 251 } |
282 return as_integer<unsigned long>( "stoul", str, idx, base ); | 252 |
283 } | 253 long double stold(const string& str, size_t* idx) { |
284 | 254 return as_float<long double>("stold", str, idx); |
285 unsigned long | 255 } |
286 stoul(const wstring& str, size_t* idx, int base) | 256 |
287 { | 257 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS |
288 return as_integer<unsigned long>( "stoul", str, idx, base ); | 258 int stoi(const wstring& str, size_t* idx, int base) { |
289 } | 259 return as_integer<int>("stoi", str, idx, base); |
290 | 260 } |
291 long long | 261 |
292 stoll(const string& str, size_t* idx, int base) | 262 long stol(const wstring& str, size_t* idx, int base) { |
293 { | 263 return as_integer<long>("stol", str, idx, base); |
294 return as_integer<long long>( "stoll", str, idx, base ); | 264 } |
295 } | 265 |
296 | 266 unsigned long stoul(const wstring& str, size_t* idx, int base) { |
297 long long | 267 return as_integer<unsigned long>("stoul", str, idx, base); |
298 stoll(const wstring& str, size_t* idx, int base) | 268 } |
299 { | 269 |
300 return as_integer<long long>( "stoll", str, idx, base ); | 270 long long stoll(const wstring& str, size_t* idx, int base) { |
301 } | 271 return as_integer<long long>("stoll", str, idx, base); |
302 | 272 } |
303 unsigned long long | 273 |
304 stoull(const string& str, size_t* idx, int base) | 274 unsigned long long stoull(const wstring& str, size_t* idx, int base) { |
305 { | 275 return as_integer<unsigned long long>("stoull", str, idx, base); |
306 return as_integer<unsigned long long>( "stoull", str, idx, base ); | 276 } |
307 } | 277 |
308 | 278 float stof(const wstring& str, size_t* idx) { |
309 unsigned long long | 279 return as_float<float>("stof", str, idx); |
310 stoull(const wstring& str, size_t* idx, int base) | 280 } |
311 { | 281 |
312 return as_integer<unsigned long long>( "stoull", str, idx, base ); | 282 double stod(const wstring& str, size_t* idx) { |
313 } | 283 return as_float<double>("stod", str, idx); |
314 | 284 } |
315 float | 285 |
316 stof(const string& str, size_t* idx) | 286 long double stold(const wstring& str, size_t* idx) { |
317 { | 287 return as_float<long double>("stold", str, idx); |
318 return as_float<float>( "stof", str, idx ); | 288 } |
319 } | 289 #endif // !_LIBCPP_HAS_NO_WIDE_CHARACTERS |
320 | |
321 float | |
322 stof(const wstring& str, size_t* idx) | |
323 { | |
324 return as_float<float>( "stof", str, idx ); | |
325 } | |
326 | |
327 double | |
328 stod(const string& str, size_t* idx) | |
329 { | |
330 return as_float<double>( "stod", str, idx ); | |
331 } | |
332 | |
333 double | |
334 stod(const wstring& str, size_t* idx) | |
335 { | |
336 return as_float<double>( "stod", str, idx ); | |
337 } | |
338 | |
339 long double | |
340 stold(const string& str, size_t* idx) | |
341 { | |
342 return as_float<long double>( "stold", str, idx ); | |
343 } | |
344 | |
345 long double | |
346 stold(const wstring& str, size_t* idx) | |
347 { | |
348 return as_float<long double>( "stold", str, idx ); | |
349 } | |
350 | 290 |
351 // to_string | 291 // to_string |
352 | 292 |
353 namespace | 293 namespace |
354 { | 294 { |
355 | 295 |
356 // as_string | 296 // as_string |
357 | 297 |
358 template<typename S, typename P, typename V > | 298 template<typename S, typename P, typename V > |
359 inline | 299 inline S as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) { |
360 S | |
361 as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a) | |
362 { | |
363 typedef typename S::size_type size_type; | 300 typedef typename S::size_type size_type; |
364 size_type available = s.size(); | 301 size_type available = s.size(); |
365 while (true) | 302 while (true) { |
366 { | |
367 int status = sprintf_like(&s[0], available + 1, fmt, a); | 303 int status = sprintf_like(&s[0], available + 1, fmt, a); |
368 if ( status >= 0 ) | 304 if (status >= 0) { |
369 { | |
370 size_type used = static_cast<size_type>(status); | 305 size_type used = static_cast<size_type>(status); |
371 if ( used <= available ) | 306 if (used <= available) { |
372 { | 307 s.resize(used); |
373 s.resize( used ); | |
374 break; | 308 break; |
375 } | 309 } |
376 available = used; // Assume this is advice of how much space we need. | 310 available = used; // Assume this is advice of how much space we need. |
377 } | 311 } |
378 else | 312 else |
384 | 318 |
385 template <class S> | 319 template <class S> |
386 struct initial_string; | 320 struct initial_string; |
387 | 321 |
388 template <> | 322 template <> |
389 struct initial_string<string> | 323 struct initial_string<string> { |
390 { | 324 string operator()() const { |
391 string | |
392 operator()() const | |
393 { | |
394 string s; | 325 string s; |
395 s.resize(s.capacity()); | 326 s.resize(s.capacity()); |
396 return s; | 327 return s; |
397 } | 328 } |
398 }; | 329 }; |
399 | 330 |
331 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS | |
400 template <> | 332 template <> |
401 struct initial_string<wstring> | 333 struct initial_string<wstring> { |
402 { | 334 wstring operator()() const { |
403 wstring | |
404 operator()() const | |
405 { | |
406 wstring s(20, wchar_t()); | 335 wstring s(20, wchar_t()); |
407 s.resize(s.capacity()); | 336 s.resize(s.capacity()); |
408 return s; | 337 return s; |
409 } | 338 } |
410 }; | 339 }; |
411 | 340 |
412 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); | 341 typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...); |
413 | 342 |
414 inline | 343 inline wide_printf get_swprintf() { |
415 wide_printf | |
416 get_swprintf() | |
417 { | |
418 #ifndef _LIBCPP_MSVCRT | 344 #ifndef _LIBCPP_MSVCRT |
419 return swprintf; | 345 return swprintf; |
420 #else | 346 #else |
421 return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); | 347 return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf); |
422 #endif | 348 #endif |
423 } | 349 } |
350 #endif // _LIBCPP_HAS_NO_WIDE_CHARACTERS | |
424 | 351 |
425 template <typename S, typename V> | 352 template <typename S, typename V> |
426 S i_to_string(V v) | 353 S i_to_string(V v) { |
427 { | |
428 // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. | 354 // numeric_limits::digits10 returns value less on 1 than desired for unsigned numbers. |
429 // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), | 355 // For example, for 1-byte unsigned value digits10 is 2 (999 can not be represented), |
430 // so we need +1 here. | 356 // so we need +1 here. |
431 constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 | 357 constexpr size_t bufsize = numeric_limits<V>::digits10 + 2; // +1 for minus, +1 for digits10 |
432 char buf[bufsize]; | 358 char buf[bufsize]; |
442 string to_string (long long val) { return i_to_string< string>(val); } | 368 string to_string (long long val) { return i_to_string< string>(val); } |
443 string to_string (unsigned val) { return i_to_string< string>(val); } | 369 string to_string (unsigned val) { return i_to_string< string>(val); } |
444 string to_string (unsigned long val) { return i_to_string< string>(val); } | 370 string to_string (unsigned long val) { return i_to_string< string>(val); } |
445 string to_string (unsigned long long val) { return i_to_string< string>(val); } | 371 string to_string (unsigned long long val) { return i_to_string< string>(val); } |
446 | 372 |
373 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS | |
447 wstring to_wstring(int val) { return i_to_string<wstring>(val); } | 374 wstring to_wstring(int val) { return i_to_string<wstring>(val); } |
448 wstring to_wstring(long val) { return i_to_string<wstring>(val); } | 375 wstring to_wstring(long val) { return i_to_string<wstring>(val); } |
449 wstring to_wstring(long long val) { return i_to_string<wstring>(val); } | 376 wstring to_wstring(long long val) { return i_to_string<wstring>(val); } |
450 wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } | 377 wstring to_wstring(unsigned val) { return i_to_string<wstring>(val); } |
451 wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } | 378 wstring to_wstring(unsigned long val) { return i_to_string<wstring>(val); } |
452 wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } | 379 wstring to_wstring(unsigned long long val) { return i_to_string<wstring>(val); } |
453 | 380 #endif |
454 | 381 |
455 string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } | 382 string to_string (float val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } |
456 string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } | 383 string to_string (double val) { return as_string(snprintf, initial_string< string>()(), "%f", val); } |
457 string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } | 384 string to_string (long double val) { return as_string(snprintf, initial_string< string>()(), "%Lf", val); } |
458 | 385 |
386 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS | |
459 wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } | 387 wstring to_wstring(float val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } |
460 wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } | 388 wstring to_wstring(double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%f", val); } |
461 wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } | 389 wstring to_wstring(long double val) { return as_string(get_swprintf(), initial_string<wstring>()(), L"%Lf", val); } |
390 #endif | |
462 | 391 |
463 _LIBCPP_END_NAMESPACE_STD | 392 _LIBCPP_END_NAMESPACE_STD |