Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
wine-mirror
GitHub Repository: wine-mirror/wine
Path: blob/master/libs/c++/src/string.cpp
12346 views
1
//===------------------------- string.cpp ---------------------------------===//
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
#include "string"
11
#include "cstdlib"
12
#include "cwchar"
13
#include "cerrno"
14
#include "limits"
15
#include "stdexcept"
16
#include <stdio.h>
17
18
_LIBCPP_BEGIN_NAMESPACE_STD
19
20
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common<true>;
21
22
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<char>;
23
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS basic_string<wchar_t>;
24
25
template
26
string
27
operator+<char, char_traits<char>, allocator<char> >(char const*, string const&);
28
29
namespace
30
{
31
32
template<typename T>
33
inline
34
void throw_helper( const string& msg )
35
{
36
#ifndef _LIBCPP_NO_EXCEPTIONS
37
throw T( msg );
38
#else
39
fprintf(stderr, "%s\n", msg.c_str());
40
_VSTD::abort();
41
#endif
42
}
43
44
inline
45
void throw_from_string_out_of_range( const string& func )
46
{
47
throw_helper<out_of_range>(func + ": out of range");
48
}
49
50
inline
51
void throw_from_string_invalid_arg( const string& func )
52
{
53
throw_helper<invalid_argument>(func + ": no conversion");
54
}
55
56
// as_integer
57
58
template<typename V, typename S, typename F>
59
inline
60
V
61
as_integer_helper(const string& func, const S& str, size_t* idx, int base, F f)
62
{
63
typename S::value_type* ptr = nullptr;
64
const typename S::value_type* const p = str.c_str();
65
typename remove_reference<decltype(errno)>::type errno_save = errno;
66
errno = 0;
67
V r = f(p, &ptr, base);
68
swap(errno, errno_save);
69
if (errno_save == ERANGE)
70
throw_from_string_out_of_range(func);
71
if (ptr == p)
72
throw_from_string_invalid_arg(func);
73
if (idx)
74
*idx = static_cast<size_t>(ptr - p);
75
return r;
76
}
77
78
template<typename V, typename S>
79
inline
80
V
81
as_integer(const string& func, const S& s, size_t* idx, int base);
82
83
// string
84
template<>
85
inline
86
int
87
as_integer(const string& func, const string& s, size_t* idx, int base )
88
{
89
// Use long as no Standard string to integer exists.
90
long r = as_integer_helper<long>( func, s, idx, base, strtol );
91
if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
92
throw_from_string_out_of_range(func);
93
return static_cast<int>(r);
94
}
95
96
template<>
97
inline
98
long
99
as_integer(const string& func, const string& s, size_t* idx, int base )
100
{
101
return as_integer_helper<long>( func, s, idx, base, strtol );
102
}
103
104
template<>
105
inline
106
unsigned long
107
as_integer( const string& func, const string& s, size_t* idx, int base )
108
{
109
return as_integer_helper<unsigned long>( func, s, idx, base, strtoul );
110
}
111
112
template<>
113
inline
114
long long
115
as_integer( const string& func, const string& s, size_t* idx, int base )
116
{
117
return as_integer_helper<long long>( func, s, idx, base, strtoll );
118
}
119
120
template<>
121
inline
122
unsigned long long
123
as_integer( const string& func, const string& s, size_t* idx, int base )
124
{
125
return as_integer_helper<unsigned long long>( func, s, idx, base, strtoull );
126
}
127
128
// wstring
129
template<>
130
inline
131
int
132
as_integer( const string& func, const wstring& s, size_t* idx, int base )
133
{
134
// Use long as no Stantard string to integer exists.
135
long r = as_integer_helper<long>( func, s, idx, base, wcstol );
136
if (r < numeric_limits<int>::min() || numeric_limits<int>::max() < r)
137
throw_from_string_out_of_range(func);
138
return static_cast<int>(r);
139
}
140
141
template<>
142
inline
143
long
144
as_integer( const string& func, const wstring& s, size_t* idx, int base )
145
{
146
return as_integer_helper<long>( func, s, idx, base, wcstol );
147
}
148
149
template<>
150
inline
151
unsigned long
152
as_integer( const string& func, const wstring& s, size_t* idx, int base )
153
{
154
return as_integer_helper<unsigned long>( func, s, idx, base, wcstoul );
155
}
156
157
template<>
158
inline
159
long long
160
as_integer( const string& func, const wstring& s, size_t* idx, int base )
161
{
162
return as_integer_helper<long long>( func, s, idx, base, wcstoll );
163
}
164
165
template<>
166
inline
167
unsigned long long
168
as_integer( const string& func, const wstring& s, size_t* idx, int base )
169
{
170
return as_integer_helper<unsigned long long>( func, s, idx, base, wcstoull );
171
}
172
173
// as_float
174
175
template<typename V, typename S, typename F>
176
inline
177
V
178
as_float_helper(const string& func, const S& str, size_t* idx, F f )
179
{
180
typename S::value_type* ptr = nullptr;
181
const typename S::value_type* const p = str.c_str();
182
typename remove_reference<decltype(errno)>::type errno_save = errno;
183
errno = 0;
184
V r = f(p, &ptr);
185
swap(errno, errno_save);
186
if (errno_save == ERANGE)
187
throw_from_string_out_of_range(func);
188
if (ptr == p)
189
throw_from_string_invalid_arg(func);
190
if (idx)
191
*idx = static_cast<size_t>(ptr - p);
192
return r;
193
}
194
195
template<typename V, typename S>
196
inline
197
V as_float( const string& func, const S& s, size_t* idx = nullptr );
198
199
template<>
200
inline
201
float
202
as_float( const string& func, const string& s, size_t* idx )
203
{
204
return as_float_helper<float>( func, s, idx, strtof );
205
}
206
207
template<>
208
inline
209
double
210
as_float(const string& func, const string& s, size_t* idx )
211
{
212
return as_float_helper<double>( func, s, idx, strtod );
213
}
214
215
template<>
216
inline
217
long double
218
as_float( const string& func, const string& s, size_t* idx )
219
{
220
return as_float_helper<long double>( func, s, idx, strtold );
221
}
222
223
template<>
224
inline
225
float
226
as_float( const string& func, const wstring& s, size_t* idx )
227
{
228
return as_float_helper<float>( func, s, idx, wcstof );
229
}
230
231
template<>
232
inline
233
double
234
as_float( const string& func, const wstring& s, size_t* idx )
235
{
236
return as_float_helper<double>( func, s, idx, wcstod );
237
}
238
239
template<>
240
inline
241
long double
242
as_float( const string& func, const wstring& s, size_t* idx )
243
{
244
return as_float_helper<long double>( func, s, idx, wcstold );
245
}
246
247
} // unnamed namespace
248
249
int
250
stoi(const string& str, size_t* idx, int base)
251
{
252
return as_integer<int>( "stoi", str, idx, base );
253
}
254
255
int
256
stoi(const wstring& str, size_t* idx, int base)
257
{
258
return as_integer<int>( "stoi", str, idx, base );
259
}
260
261
long
262
stol(const string& str, size_t* idx, int base)
263
{
264
return as_integer<long>( "stol", str, idx, base );
265
}
266
267
long
268
stol(const wstring& str, size_t* idx, int base)
269
{
270
return as_integer<long>( "stol", str, idx, base );
271
}
272
273
unsigned long
274
stoul(const string& str, size_t* idx, int base)
275
{
276
return as_integer<unsigned long>( "stoul", str, idx, base );
277
}
278
279
unsigned long
280
stoul(const wstring& str, size_t* idx, int base)
281
{
282
return as_integer<unsigned long>( "stoul", str, idx, base );
283
}
284
285
long long
286
stoll(const string& str, size_t* idx, int base)
287
{
288
return as_integer<long long>( "stoll", str, idx, base );
289
}
290
291
long long
292
stoll(const wstring& str, size_t* idx, int base)
293
{
294
return as_integer<long long>( "stoll", str, idx, base );
295
}
296
297
unsigned long long
298
stoull(const string& str, size_t* idx, int base)
299
{
300
return as_integer<unsigned long long>( "stoull", str, idx, base );
301
}
302
303
unsigned long long
304
stoull(const wstring& str, size_t* idx, int base)
305
{
306
return as_integer<unsigned long long>( "stoull", str, idx, base );
307
}
308
309
float
310
stof(const string& str, size_t* idx)
311
{
312
return as_float<float>( "stof", str, idx );
313
}
314
315
float
316
stof(const wstring& str, size_t* idx)
317
{
318
return as_float<float>( "stof", str, idx );
319
}
320
321
double
322
stod(const string& str, size_t* idx)
323
{
324
return as_float<double>( "stod", str, idx );
325
}
326
327
double
328
stod(const wstring& str, size_t* idx)
329
{
330
return as_float<double>( "stod", str, idx );
331
}
332
333
long double
334
stold(const string& str, size_t* idx)
335
{
336
return as_float<long double>( "stold", str, idx );
337
}
338
339
long double
340
stold(const wstring& str, size_t* idx)
341
{
342
return as_float<long double>( "stold", str, idx );
343
}
344
345
// to_string
346
347
namespace
348
{
349
350
// as_string
351
352
template<typename S, typename P, typename V >
353
inline
354
S
355
as_string(P sprintf_like, S s, const typename S::value_type* fmt, V a)
356
{
357
typedef typename S::size_type size_type;
358
size_type available = s.size();
359
while (true)
360
{
361
int status = sprintf_like(&s[0], available + 1, fmt, a);
362
if ( status >= 0 )
363
{
364
size_type used = static_cast<size_type>(status);
365
if ( used <= available )
366
{
367
s.resize( used );
368
break;
369
}
370
available = used; // Assume this is advice of how much space we need.
371
}
372
else
373
available = available * 2 + 1;
374
s.resize(available);
375
}
376
return s;
377
}
378
379
template <class S, class V, bool = is_floating_point<V>::value>
380
struct initial_string;
381
382
template <class V, bool b>
383
struct initial_string<string, V, b>
384
{
385
string
386
operator()() const
387
{
388
string s;
389
s.resize(s.capacity());
390
return s;
391
}
392
};
393
394
template <class V>
395
struct initial_string<wstring, V, false>
396
{
397
wstring
398
operator()() const
399
{
400
const size_t n = (numeric_limits<unsigned long long>::digits / 3)
401
+ ((numeric_limits<unsigned long long>::digits % 3) != 0)
402
+ 1;
403
wstring s(n, wchar_t());
404
s.resize(s.capacity());
405
return s;
406
}
407
};
408
409
template <class V>
410
struct initial_string<wstring, V, true>
411
{
412
wstring
413
operator()() const
414
{
415
wstring s(20, wchar_t());
416
s.resize(s.capacity());
417
return s;
418
}
419
};
420
421
typedef int (*wide_printf)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...);
422
423
inline
424
wide_printf
425
get_swprintf()
426
{
427
#ifndef _LIBCPP_MSVCRT
428
return swprintf;
429
#else
430
return static_cast<int (__cdecl*)(wchar_t* __restrict, size_t, const wchar_t*__restrict, ...)>(_snwprintf);
431
#endif
432
}
433
434
} // unnamed namespace
435
436
string to_string(int val)
437
{
438
return as_string(snprintf, initial_string<string, int>()(), "%d", val);
439
}
440
441
string to_string(unsigned val)
442
{
443
return as_string(snprintf, initial_string<string, unsigned>()(), "%u", val);
444
}
445
446
string to_string(long val)
447
{
448
return as_string(snprintf, initial_string<string, long>()(), "%ld", val);
449
}
450
451
string to_string(unsigned long val)
452
{
453
return as_string(snprintf, initial_string<string, unsigned long>()(), "%lu", val);
454
}
455
456
string to_string(long long val)
457
{
458
return as_string(snprintf, initial_string<string, long long>()(), "%lld", val);
459
}
460
461
string to_string(unsigned long long val)
462
{
463
return as_string(snprintf, initial_string<string, unsigned long long>()(), "%llu", val);
464
}
465
466
string to_string(float val)
467
{
468
return as_string(snprintf, initial_string<string, float>()(), "%f", val);
469
}
470
471
string to_string(double val)
472
{
473
return as_string(snprintf, initial_string<string, double>()(), "%f", val);
474
}
475
476
string to_string(long double val)
477
{
478
return as_string(snprintf, initial_string<string, long double>()(), "%Lf", val);
479
}
480
481
wstring to_wstring(int val)
482
{
483
return as_string(get_swprintf(), initial_string<wstring, int>()(), L"%d", val);
484
}
485
486
wstring to_wstring(unsigned val)
487
{
488
return as_string(get_swprintf(), initial_string<wstring, unsigned>()(), L"%u", val);
489
}
490
491
wstring to_wstring(long val)
492
{
493
return as_string(get_swprintf(), initial_string<wstring, long>()(), L"%ld", val);
494
}
495
496
wstring to_wstring(unsigned long val)
497
{
498
return as_string(get_swprintf(), initial_string<wstring, unsigned long>()(), L"%lu", val);
499
}
500
501
wstring to_wstring(long long val)
502
{
503
return as_string(get_swprintf(), initial_string<wstring, long long>()(), L"%lld", val);
504
}
505
506
wstring to_wstring(unsigned long long val)
507
{
508
return as_string(get_swprintf(), initial_string<wstring, unsigned long long>()(), L"%llu", val);
509
}
510
511
wstring to_wstring(float val)
512
{
513
return as_string(get_swprintf(), initial_string<wstring, float>()(), L"%f", val);
514
}
515
516
wstring to_wstring(double val)
517
{
518
return as_string(get_swprintf(), initial_string<wstring, double>()(), L"%f", val);
519
}
520
521
wstring to_wstring(long double val)
522
{
523
return as_string(get_swprintf(), initial_string<wstring, long double>()(), L"%Lf", val);
524
}
525
_LIBCPP_END_NAMESPACE_STD
526
527