Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/include/__locale_dir/money.h
213766 views
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
#ifndef _LIBCPP___LOCALE_DIR_MONEY_H
10
#define _LIBCPP___LOCALE_DIR_MONEY_H
11
12
#include <__algorithm/copy.h>
13
#include <__algorithm/equal.h>
14
#include <__algorithm/find.h>
15
#include <__algorithm/reverse.h>
16
#include <__config>
17
#include <__locale>
18
#include <__locale_dir/check_grouping.h>
19
#include <__locale_dir/get_c_locale.h>
20
#include <__locale_dir/pad_and_output.h>
21
#include <__memory/unique_ptr.h>
22
#include <ios>
23
#include <string>
24
25
#if _LIBCPP_HAS_LOCALIZATION
26
27
# if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
28
# pragma GCC system_header
29
# endif
30
31
_LIBCPP_PUSH_MACROS
32
# include <__undef_macros>
33
34
_LIBCPP_BEGIN_NAMESPACE_STD
35
36
// money_base
37
38
class _LIBCPP_EXPORTED_FROM_ABI money_base {
39
public:
40
enum part { none, space, symbol, sign, value };
41
struct pattern {
42
char field[4];
43
};
44
45
_LIBCPP_HIDE_FROM_ABI money_base() {}
46
};
47
48
// moneypunct
49
50
template <class _CharT, bool _International = false>
51
class moneypunct : public locale::facet, public money_base {
52
public:
53
typedef _CharT char_type;
54
typedef basic_string<char_type> string_type;
55
56
_LIBCPP_HIDE_FROM_ABI explicit moneypunct(size_t __refs = 0) : locale::facet(__refs) {}
57
58
_LIBCPP_HIDE_FROM_ABI char_type decimal_point() const { return do_decimal_point(); }
59
_LIBCPP_HIDE_FROM_ABI char_type thousands_sep() const { return do_thousands_sep(); }
60
_LIBCPP_HIDE_FROM_ABI string grouping() const { return do_grouping(); }
61
_LIBCPP_HIDE_FROM_ABI string_type curr_symbol() const { return do_curr_symbol(); }
62
_LIBCPP_HIDE_FROM_ABI string_type positive_sign() const { return do_positive_sign(); }
63
_LIBCPP_HIDE_FROM_ABI string_type negative_sign() const { return do_negative_sign(); }
64
_LIBCPP_HIDE_FROM_ABI int frac_digits() const { return do_frac_digits(); }
65
_LIBCPP_HIDE_FROM_ABI pattern pos_format() const { return do_pos_format(); }
66
_LIBCPP_HIDE_FROM_ABI pattern neg_format() const { return do_neg_format(); }
67
68
static locale::id id;
69
static const bool intl = _International;
70
71
protected:
72
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct() override {}
73
74
virtual char_type do_decimal_point() const { return numeric_limits<char_type>::max(); }
75
virtual char_type do_thousands_sep() const { return numeric_limits<char_type>::max(); }
76
virtual string do_grouping() const { return string(); }
77
virtual string_type do_curr_symbol() const { return string_type(); }
78
virtual string_type do_positive_sign() const { return string_type(); }
79
virtual string_type do_negative_sign() const { return string_type(1, '-'); }
80
virtual int do_frac_digits() const { return 0; }
81
virtual pattern do_pos_format() const {
82
pattern __p = {{symbol, sign, none, value}};
83
return __p;
84
}
85
virtual pattern do_neg_format() const {
86
pattern __p = {{symbol, sign, none, value}};
87
return __p;
88
}
89
};
90
91
template <class _CharT, bool _International>
92
locale::id moneypunct<_CharT, _International>::id;
93
94
template <class _CharT, bool _International>
95
const bool moneypunct<_CharT, _International>::intl;
96
97
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, false>;
98
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<char, true>;
99
# if _LIBCPP_HAS_WIDE_CHARACTERS
100
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, false>;
101
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct<wchar_t, true>;
102
# endif
103
104
// moneypunct_byname
105
106
template <class _CharT, bool _International = false>
107
class moneypunct_byname : public moneypunct<_CharT, _International> {
108
public:
109
typedef money_base::pattern pattern;
110
typedef _CharT char_type;
111
typedef basic_string<char_type> string_type;
112
113
_LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const char* __nm, size_t __refs = 0)
114
: moneypunct<_CharT, _International>(__refs) {
115
init(__nm);
116
}
117
118
_LIBCPP_HIDE_FROM_ABI explicit moneypunct_byname(const string& __nm, size_t __refs = 0)
119
: moneypunct<_CharT, _International>(__refs) {
120
init(__nm.c_str());
121
}
122
123
protected:
124
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~moneypunct_byname() override {}
125
126
char_type do_decimal_point() const override { return __decimal_point_; }
127
char_type do_thousands_sep() const override { return __thousands_sep_; }
128
string do_grouping() const override { return __grouping_; }
129
string_type do_curr_symbol() const override { return __curr_symbol_; }
130
string_type do_positive_sign() const override { return __positive_sign_; }
131
string_type do_negative_sign() const override { return __negative_sign_; }
132
int do_frac_digits() const override { return __frac_digits_; }
133
pattern do_pos_format() const override { return __pos_format_; }
134
pattern do_neg_format() const override { return __neg_format_; }
135
136
private:
137
char_type __decimal_point_;
138
char_type __thousands_sep_;
139
string __grouping_;
140
string_type __curr_symbol_;
141
string_type __positive_sign_;
142
string_type __negative_sign_;
143
int __frac_digits_;
144
pattern __pos_format_;
145
pattern __neg_format_;
146
147
void init(const char*);
148
};
149
150
template <>
151
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, false>::init(const char*);
152
template <>
153
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<char, true>::init(const char*);
154
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, false>;
155
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<char, true>;
156
157
# if _LIBCPP_HAS_WIDE_CHARACTERS
158
template <>
159
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, false>::init(const char*);
160
template <>
161
_LIBCPP_EXPORTED_FROM_ABI void moneypunct_byname<wchar_t, true>::init(const char*);
162
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, false>;
163
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS moneypunct_byname<wchar_t, true>;
164
# endif
165
166
// money_get
167
168
template <class _CharT>
169
class __money_get {
170
protected:
171
typedef _CharT char_type;
172
typedef basic_string<char_type> string_type;
173
174
_LIBCPP_HIDE_FROM_ABI __money_get() {}
175
176
static void __gather_info(
177
bool __intl,
178
const locale& __loc,
179
money_base::pattern& __pat,
180
char_type& __dp,
181
char_type& __ts,
182
string& __grp,
183
string_type& __sym,
184
string_type& __psn,
185
string_type& __nsn,
186
int& __fd);
187
};
188
189
template <class _CharT>
190
void __money_get<_CharT>::__gather_info(
191
bool __intl,
192
const locale& __loc,
193
money_base::pattern& __pat,
194
char_type& __dp,
195
char_type& __ts,
196
string& __grp,
197
string_type& __sym,
198
string_type& __psn,
199
string_type& __nsn,
200
int& __fd) {
201
if (__intl) {
202
const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);
203
__pat = __mp.neg_format();
204
__nsn = __mp.negative_sign();
205
__psn = __mp.positive_sign();
206
__dp = __mp.decimal_point();
207
__ts = __mp.thousands_sep();
208
__grp = __mp.grouping();
209
__sym = __mp.curr_symbol();
210
__fd = __mp.frac_digits();
211
} else {
212
const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);
213
__pat = __mp.neg_format();
214
__nsn = __mp.negative_sign();
215
__psn = __mp.positive_sign();
216
__dp = __mp.decimal_point();
217
__ts = __mp.thousands_sep();
218
__grp = __mp.grouping();
219
__sym = __mp.curr_symbol();
220
__fd = __mp.frac_digits();
221
}
222
}
223
224
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<char>;
225
# if _LIBCPP_HAS_WIDE_CHARACTERS
226
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_get<wchar_t>;
227
# endif
228
229
template <class _CharT, class _InputIterator = istreambuf_iterator<_CharT> >
230
class money_get : public locale::facet, private __money_get<_CharT> {
231
public:
232
typedef _CharT char_type;
233
typedef _InputIterator iter_type;
234
typedef basic_string<char_type> string_type;
235
236
_LIBCPP_HIDE_FROM_ABI explicit money_get(size_t __refs = 0) : locale::facet(__refs) {}
237
238
_LIBCPP_HIDE_FROM_ABI iter_type
239
get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {
240
return do_get(__b, __e, __intl, __iob, __err, __v);
241
}
242
243
_LIBCPP_HIDE_FROM_ABI iter_type
244
get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {
245
return do_get(__b, __e, __intl, __iob, __err, __v);
246
}
247
248
static locale::id id;
249
250
protected:
251
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_get() override {}
252
253
virtual iter_type
254
do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const;
255
virtual iter_type
256
do_get(iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const;
257
258
private:
259
static bool __do_get(
260
iter_type& __b,
261
iter_type __e,
262
bool __intl,
263
const locale& __loc,
264
ios_base::fmtflags __flags,
265
ios_base::iostate& __err,
266
bool& __neg,
267
const ctype<char_type>& __ct,
268
unique_ptr<char_type, void (*)(void*)>& __wb,
269
char_type*& __wn,
270
char_type* __we);
271
};
272
273
template <class _CharT, class _InputIterator>
274
locale::id money_get<_CharT, _InputIterator>::id;
275
276
_LIBCPP_EXPORTED_FROM_ABI void __do_nothing(void*);
277
278
template <class _Tp>
279
_LIBCPP_HIDE_FROM_ABI void __double_or_nothing(unique_ptr<_Tp, void (*)(void*)>& __b, _Tp*& __n, _Tp*& __e) {
280
bool __owns = __b.get_deleter() != __do_nothing;
281
size_t __cur_cap = static_cast<size_t>(__e - __b.get()) * sizeof(_Tp);
282
size_t __new_cap = __cur_cap < numeric_limits<size_t>::max() / 2 ? 2 * __cur_cap : numeric_limits<size_t>::max();
283
if (__new_cap == 0)
284
__new_cap = sizeof(_Tp);
285
size_t __n_off = static_cast<size_t>(__n - __b.get());
286
_Tp* __t = (_Tp*)std::realloc(__owns ? __b.get() : 0, __new_cap);
287
if (__t == 0)
288
std::__throw_bad_alloc();
289
if (__owns)
290
__b.release();
291
else
292
std::memcpy(__t, __b.get(), __cur_cap);
293
__b = unique_ptr<_Tp, void (*)(void*)>(__t, free);
294
__new_cap /= sizeof(_Tp);
295
__n = __b.get() + __n_off;
296
__e = __b.get() + __new_cap;
297
}
298
299
// true == success
300
template <class _CharT, class _InputIterator>
301
bool money_get<_CharT, _InputIterator>::__do_get(
302
iter_type& __b,
303
iter_type __e,
304
bool __intl,
305
const locale& __loc,
306
ios_base::fmtflags __flags,
307
ios_base::iostate& __err,
308
bool& __neg,
309
const ctype<char_type>& __ct,
310
unique_ptr<char_type, void (*)(void*)>& __wb,
311
char_type*& __wn,
312
char_type* __we) {
313
if (__b == __e) {
314
__err |= ios_base::failbit;
315
return false;
316
}
317
const unsigned __bz = 100;
318
unsigned __gbuf[__bz];
319
unique_ptr<unsigned, void (*)(void*)> __gb(__gbuf, __do_nothing);
320
unsigned* __gn = __gb.get();
321
unsigned* __ge = __gn + __bz;
322
money_base::pattern __pat;
323
char_type __dp;
324
char_type __ts;
325
string __grp;
326
string_type __sym;
327
string_type __psn;
328
string_type __nsn;
329
// Capture the spaces read into money_base::{space,none} so they
330
// can be compared to initial spaces in __sym.
331
string_type __spaces;
332
int __fd;
333
__money_get<_CharT>::__gather_info(__intl, __loc, __pat, __dp, __ts, __grp, __sym, __psn, __nsn, __fd);
334
const string_type* __trailing_sign = 0;
335
__wn = __wb.get();
336
for (unsigned __p = 0; __p < 4 && __b != __e; ++__p) {
337
switch (__pat.field[__p]) {
338
case money_base::space:
339
if (__p != 3) {
340
if (__ct.is(ctype_base::space, *__b))
341
__spaces.push_back(*__b++);
342
else {
343
__err |= ios_base::failbit;
344
return false;
345
}
346
}
347
[[__fallthrough__]];
348
case money_base::none:
349
if (__p != 3) {
350
while (__b != __e && __ct.is(ctype_base::space, *__b))
351
__spaces.push_back(*__b++);
352
}
353
break;
354
case money_base::sign:
355
if (__psn.size() > 0 && *__b == __psn[0]) {
356
++__b;
357
__neg = false;
358
if (__psn.size() > 1)
359
__trailing_sign = std::addressof(__psn);
360
break;
361
}
362
if (__nsn.size() > 0 && *__b == __nsn[0]) {
363
++__b;
364
__neg = true;
365
if (__nsn.size() > 1)
366
__trailing_sign = std::addressof(__nsn);
367
break;
368
}
369
if (__psn.size() > 0 && __nsn.size() > 0) { // sign is required
370
__err |= ios_base::failbit;
371
return false;
372
}
373
if (__psn.size() == 0 && __nsn.size() == 0)
374
// locale has no way of specifying a sign. Use the initial value of __neg as a default
375
break;
376
__neg = (__nsn.size() == 0);
377
break;
378
case money_base::symbol: {
379
bool __more_needed =
380
__trailing_sign || (__p < 2) || (__p == 2 && __pat.field[3] != static_cast<char>(money_base::none));
381
bool __sb = (__flags & ios_base::showbase) != 0;
382
if (__sb || __more_needed) {
383
typename string_type::const_iterator __sym_space_end = __sym.begin();
384
if (__p > 0 && (__pat.field[__p - 1] == money_base::none || __pat.field[__p - 1] == money_base::space)) {
385
// Match spaces we've already read against spaces at
386
// the beginning of __sym.
387
while (__sym_space_end != __sym.end() && __ct.is(ctype_base::space, *__sym_space_end))
388
++__sym_space_end;
389
const size_t __num_spaces = __sym_space_end - __sym.begin();
390
if (__num_spaces > __spaces.size() ||
391
!std::equal(__spaces.end() - __num_spaces, __spaces.end(), __sym.begin())) {
392
// No match. Put __sym_space_end back at the
393
// beginning of __sym, which will prevent a
394
// match in the next loop.
395
__sym_space_end = __sym.begin();
396
}
397
}
398
typename string_type::const_iterator __sym_curr_char = __sym_space_end;
399
while (__sym_curr_char != __sym.end() && __b != __e && *__b == *__sym_curr_char) {
400
++__b;
401
++__sym_curr_char;
402
}
403
if (__sb && __sym_curr_char != __sym.end()) {
404
__err |= ios_base::failbit;
405
return false;
406
}
407
}
408
} break;
409
case money_base::value: {
410
unsigned __ng = 0;
411
for (; __b != __e; ++__b) {
412
char_type __c = *__b;
413
if (__ct.is(ctype_base::digit, __c)) {
414
if (__wn == __we)
415
std::__double_or_nothing(__wb, __wn, __we);
416
*__wn++ = __c;
417
++__ng;
418
} else if (__grp.size() > 0 && __ng > 0 && __c == __ts) {
419
if (__gn == __ge)
420
std::__double_or_nothing(__gb, __gn, __ge);
421
*__gn++ = __ng;
422
__ng = 0;
423
} else
424
break;
425
}
426
if (__gb.get() != __gn && __ng > 0) {
427
if (__gn == __ge)
428
std::__double_or_nothing(__gb, __gn, __ge);
429
*__gn++ = __ng;
430
}
431
if (__fd > 0) {
432
if (__b == __e || *__b != __dp) {
433
__err |= ios_base::failbit;
434
return false;
435
}
436
for (++__b; __fd > 0; --__fd, ++__b) {
437
if (__b == __e || !__ct.is(ctype_base::digit, *__b)) {
438
__err |= ios_base::failbit;
439
return false;
440
}
441
if (__wn == __we)
442
std::__double_or_nothing(__wb, __wn, __we);
443
*__wn++ = *__b;
444
}
445
}
446
if (__wn == __wb.get()) {
447
__err |= ios_base::failbit;
448
return false;
449
}
450
} break;
451
}
452
}
453
if (__trailing_sign) {
454
for (unsigned __i = 1; __i < __trailing_sign->size(); ++__i, ++__b) {
455
if (__b == __e || *__b != (*__trailing_sign)[__i]) {
456
__err |= ios_base::failbit;
457
return false;
458
}
459
}
460
}
461
if (__gb.get() != __gn) {
462
ios_base::iostate __et = ios_base::goodbit;
463
__check_grouping(__grp, __gb.get(), __gn, __et);
464
if (__et) {
465
__err |= ios_base::failbit;
466
return false;
467
}
468
}
469
return true;
470
}
471
472
template <class _CharT, class _InputIterator>
473
_InputIterator money_get<_CharT, _InputIterator>::do_get(
474
iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, long double& __v) const {
475
const int __bz = 100;
476
char_type __wbuf[__bz];
477
unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);
478
char_type* __wn;
479
char_type* __we = __wbuf + __bz;
480
locale __loc = __iob.getloc();
481
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
482
bool __neg = false;
483
if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {
484
const char __src[] = "0123456789";
485
char_type __atoms[sizeof(__src) - 1];
486
__ct.widen(__src, __src + (sizeof(__src) - 1), __atoms);
487
char __nbuf[__bz];
488
char* __nc = __nbuf;
489
const char* __nc_in = __nc;
490
unique_ptr<char, void (*)(void*)> __h(nullptr, free);
491
if (__wn - __wb.get() > __bz - 2) {
492
__h.reset((char*)malloc(static_cast<size_t>(__wn - __wb.get() + 2)));
493
if (__h.get() == nullptr)
494
std::__throw_bad_alloc();
495
__nc = __h.get();
496
__nc_in = __nc;
497
}
498
if (__neg)
499
*__nc++ = '-';
500
for (const char_type* __w = __wb.get(); __w < __wn; ++__w, ++__nc)
501
*__nc = __src[std::find(__atoms, std::end(__atoms), *__w) - __atoms];
502
*__nc = char();
503
if (sscanf(__nc_in, "%Lf", &__v) != 1)
504
std::__throw_runtime_error("money_get error");
505
}
506
if (__b == __e)
507
__err |= ios_base::eofbit;
508
return __b;
509
}
510
511
template <class _CharT, class _InputIterator>
512
_InputIterator money_get<_CharT, _InputIterator>::do_get(
513
iter_type __b, iter_type __e, bool __intl, ios_base& __iob, ios_base::iostate& __err, string_type& __v) const {
514
const int __bz = 100;
515
char_type __wbuf[__bz];
516
unique_ptr<char_type, void (*)(void*)> __wb(__wbuf, __do_nothing);
517
char_type* __wn;
518
char_type* __we = __wbuf + __bz;
519
locale __loc = __iob.getloc();
520
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
521
bool __neg = false;
522
if (__do_get(__b, __e, __intl, __loc, __iob.flags(), __err, __neg, __ct, __wb, __wn, __we)) {
523
__v.clear();
524
if (__neg)
525
__v.push_back(__ct.widen('-'));
526
char_type __z = __ct.widen('0');
527
char_type* __w;
528
for (__w = __wb.get(); __w < __wn - 1; ++__w)
529
if (*__w != __z)
530
break;
531
__v.append(__w, __wn);
532
}
533
if (__b == __e)
534
__err |= ios_base::eofbit;
535
return __b;
536
}
537
538
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<char>;
539
# if _LIBCPP_HAS_WIDE_CHARACTERS
540
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_get<wchar_t>;
541
# endif
542
543
// money_put
544
545
template <class _CharT>
546
class __money_put {
547
protected:
548
typedef _CharT char_type;
549
typedef basic_string<char_type> string_type;
550
551
_LIBCPP_HIDE_FROM_ABI __money_put() {}
552
553
static void __gather_info(
554
bool __intl,
555
bool __neg,
556
const locale& __loc,
557
money_base::pattern& __pat,
558
char_type& __dp,
559
char_type& __ts,
560
string& __grp,
561
string_type& __sym,
562
string_type& __sn,
563
int& __fd);
564
static void __format(
565
char_type* __mb,
566
char_type*& __mi,
567
char_type*& __me,
568
ios_base::fmtflags __flags,
569
const char_type* __db,
570
const char_type* __de,
571
const ctype<char_type>& __ct,
572
bool __neg,
573
const money_base::pattern& __pat,
574
char_type __dp,
575
char_type __ts,
576
const string& __grp,
577
const string_type& __sym,
578
const string_type& __sn,
579
int __fd);
580
};
581
582
template <class _CharT>
583
void __money_put<_CharT>::__gather_info(
584
bool __intl,
585
bool __neg,
586
const locale& __loc,
587
money_base::pattern& __pat,
588
char_type& __dp,
589
char_type& __ts,
590
string& __grp,
591
string_type& __sym,
592
string_type& __sn,
593
int& __fd) {
594
if (__intl) {
595
const moneypunct<char_type, true>& __mp = std::use_facet<moneypunct<char_type, true> >(__loc);
596
if (__neg) {
597
__pat = __mp.neg_format();
598
__sn = __mp.negative_sign();
599
} else {
600
__pat = __mp.pos_format();
601
__sn = __mp.positive_sign();
602
}
603
__dp = __mp.decimal_point();
604
__ts = __mp.thousands_sep();
605
__grp = __mp.grouping();
606
__sym = __mp.curr_symbol();
607
__fd = __mp.frac_digits();
608
} else {
609
const moneypunct<char_type, false>& __mp = std::use_facet<moneypunct<char_type, false> >(__loc);
610
if (__neg) {
611
__pat = __mp.neg_format();
612
__sn = __mp.negative_sign();
613
} else {
614
__pat = __mp.pos_format();
615
__sn = __mp.positive_sign();
616
}
617
__dp = __mp.decimal_point();
618
__ts = __mp.thousands_sep();
619
__grp = __mp.grouping();
620
__sym = __mp.curr_symbol();
621
__fd = __mp.frac_digits();
622
}
623
}
624
625
template <class _CharT>
626
void __money_put<_CharT>::__format(
627
char_type* __mb,
628
char_type*& __mi,
629
char_type*& __me,
630
ios_base::fmtflags __flags,
631
const char_type* __db,
632
const char_type* __de,
633
const ctype<char_type>& __ct,
634
bool __neg,
635
const money_base::pattern& __pat,
636
char_type __dp,
637
char_type __ts,
638
const string& __grp,
639
const string_type& __sym,
640
const string_type& __sn,
641
int __fd) {
642
__me = __mb;
643
for (char __p : __pat.field) {
644
switch (__p) {
645
case money_base::none:
646
__mi = __me;
647
break;
648
case money_base::space:
649
__mi = __me;
650
*__me++ = __ct.widen(' ');
651
break;
652
case money_base::sign:
653
if (!__sn.empty())
654
*__me++ = __sn[0];
655
break;
656
case money_base::symbol:
657
if (!__sym.empty() && (__flags & ios_base::showbase))
658
__me = std::copy(__sym.begin(), __sym.end(), __me);
659
break;
660
case money_base::value: {
661
// remember start of value so we can reverse it
662
char_type* __t = __me;
663
// find beginning of digits
664
if (__neg)
665
++__db;
666
// find end of digits
667
const char_type* __d;
668
for (__d = __db; __d < __de; ++__d)
669
if (!__ct.is(ctype_base::digit, *__d))
670
break;
671
// print fractional part
672
if (__fd > 0) {
673
int __f;
674
for (__f = __fd; __d > __db && __f > 0; --__f)
675
*__me++ = *--__d;
676
char_type __z = __f > 0 ? __ct.widen('0') : char_type();
677
for (; __f > 0; --__f)
678
*__me++ = __z;
679
*__me++ = __dp;
680
}
681
// print units part
682
if (__d == __db) {
683
*__me++ = __ct.widen('0');
684
} else {
685
unsigned __ng = 0;
686
unsigned __ig = 0;
687
unsigned __gl = __grp.empty() ? numeric_limits<unsigned>::max() : static_cast<unsigned>(__grp[__ig]);
688
while (__d != __db) {
689
if (__ng == __gl) {
690
*__me++ = __ts;
691
__ng = 0;
692
if (++__ig < __grp.size())
693
__gl = __grp[__ig] == numeric_limits<char>::max()
694
? numeric_limits<unsigned>::max()
695
: static_cast<unsigned>(__grp[__ig]);
696
}
697
*__me++ = *--__d;
698
++__ng;
699
}
700
}
701
// reverse it
702
std::reverse(__t, __me);
703
} break;
704
}
705
}
706
// print rest of sign, if any
707
if (__sn.size() > 1)
708
__me = std::copy(__sn.begin() + 1, __sn.end(), __me);
709
// set alignment
710
if ((__flags & ios_base::adjustfield) == ios_base::left)
711
__mi = __me;
712
else if ((__flags & ios_base::adjustfield) != ios_base::internal)
713
__mi = __mb;
714
}
715
716
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<char>;
717
# if _LIBCPP_HAS_WIDE_CHARACTERS
718
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS __money_put<wchar_t>;
719
# endif
720
721
template <class _CharT, class _OutputIterator = ostreambuf_iterator<_CharT> >
722
class money_put : public locale::facet, private __money_put<_CharT> {
723
public:
724
typedef _CharT char_type;
725
typedef _OutputIterator iter_type;
726
typedef basic_string<char_type> string_type;
727
728
_LIBCPP_HIDE_FROM_ABI explicit money_put(size_t __refs = 0) : locale::facet(__refs) {}
729
730
_LIBCPP_HIDE_FROM_ABI iter_type
731
put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {
732
return do_put(__s, __intl, __iob, __fl, __units);
733
}
734
735
_LIBCPP_HIDE_FROM_ABI iter_type
736
put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {
737
return do_put(__s, __intl, __iob, __fl, __digits);
738
}
739
740
static locale::id id;
741
742
protected:
743
_LIBCPP_HIDE_FROM_ABI_VIRTUAL ~money_put() override {}
744
745
virtual iter_type do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const;
746
virtual iter_type
747
do_put(iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const;
748
};
749
750
template <class _CharT, class _OutputIterator>
751
locale::id money_put<_CharT, _OutputIterator>::id;
752
753
template <class _CharT, class _OutputIterator>
754
_OutputIterator money_put<_CharT, _OutputIterator>::do_put(
755
iter_type __s, bool __intl, ios_base& __iob, char_type __fl, long double __units) const {
756
// convert to char
757
const size_t __bs = 100;
758
char __buf[__bs];
759
char* __bb = __buf;
760
char_type __digits[__bs];
761
char_type* __db = __digits;
762
int __n = snprintf(__bb, __bs, "%.0Lf", __units);
763
unique_ptr<char, void (*)(void*)> __hn(nullptr, free);
764
unique_ptr<char_type, void (*)(void*)> __hd(0, free);
765
// secure memory for digit storage
766
if (static_cast<size_t>(__n) > __bs - 1) {
767
__n = __locale::__asprintf(&__bb, _LIBCPP_GET_C_LOCALE, "%.0Lf", __units);
768
if (__n == -1)
769
std::__throw_bad_alloc();
770
__hn.reset(__bb);
771
__hd.reset((char_type*)malloc(static_cast<size_t>(__n) * sizeof(char_type)));
772
if (__hd == nullptr)
773
std::__throw_bad_alloc();
774
__db = __hd.get();
775
}
776
// gather info
777
locale __loc = __iob.getloc();
778
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
779
__ct.widen(__bb, __bb + __n, __db);
780
bool __neg = __n > 0 && __bb[0] == '-';
781
money_base::pattern __pat;
782
char_type __dp;
783
char_type __ts;
784
string __grp;
785
string_type __sym;
786
string_type __sn;
787
int __fd;
788
this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
789
// secure memory for formatting
790
char_type __mbuf[__bs];
791
char_type* __mb = __mbuf;
792
unique_ptr<char_type, void (*)(void*)> __hw(0, free);
793
size_t __exn = __n > __fd ? (static_cast<size_t>(__n) - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() +
794
static_cast<size_t>(__fd) + 1
795
: __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
796
if (__exn > __bs) {
797
__hw.reset((char_type*)malloc(__exn * sizeof(char_type)));
798
__mb = __hw.get();
799
if (__mb == 0)
800
std::__throw_bad_alloc();
801
}
802
// format
803
char_type* __mi;
804
char_type* __me;
805
this->__format(
806
__mb, __mi, __me, __iob.flags(), __db, __db + __n, __ct, __neg, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
807
return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
808
}
809
810
template <class _CharT, class _OutputIterator>
811
_OutputIterator money_put<_CharT, _OutputIterator>::do_put(
812
iter_type __s, bool __intl, ios_base& __iob, char_type __fl, const string_type& __digits) const {
813
// gather info
814
locale __loc = __iob.getloc();
815
const ctype<char_type>& __ct = std::use_facet<ctype<char_type> >(__loc);
816
bool __neg = __digits.size() > 0 && __digits[0] == __ct.widen('-');
817
money_base::pattern __pat;
818
char_type __dp;
819
char_type __ts;
820
string __grp;
821
string_type __sym;
822
string_type __sn;
823
int __fd;
824
this->__gather_info(__intl, __neg, __loc, __pat, __dp, __ts, __grp, __sym, __sn, __fd);
825
// secure memory for formatting
826
char_type __mbuf[100];
827
char_type* __mb = __mbuf;
828
unique_ptr<char_type, void (*)(void*)> __h(0, free);
829
size_t __exn =
830
static_cast<int>(__digits.size()) > __fd
831
? (__digits.size() - static_cast<size_t>(__fd)) * 2 + __sn.size() + __sym.size() + static_cast<size_t>(__fd) +
832
1
833
: __sn.size() + __sym.size() + static_cast<size_t>(__fd) + 2;
834
if (__exn > 100) {
835
__h.reset((char_type*)malloc(__exn * sizeof(char_type)));
836
__mb = __h.get();
837
if (__mb == 0)
838
std::__throw_bad_alloc();
839
}
840
// format
841
char_type* __mi;
842
char_type* __me;
843
this->__format(
844
__mb,
845
__mi,
846
__me,
847
__iob.flags(),
848
__digits.data(),
849
__digits.data() + __digits.size(),
850
__ct,
851
__neg,
852
__pat,
853
__dp,
854
__ts,
855
__grp,
856
__sym,
857
__sn,
858
__fd);
859
return std::__pad_and_output(__s, __mb, __mi, __me, __iob, __fl);
860
}
861
862
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<char>;
863
# if _LIBCPP_HAS_WIDE_CHARACTERS
864
extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS money_put<wchar_t>;
865
# endif
866
867
_LIBCPP_END_NAMESPACE_STD
868
869
_LIBCPP_POP_MACROS
870
871
#endif // _LIBCPP_HAS_LOCALIZATION
872
873
#endif // _LIBCPP___LOCALE_DIR_MONEY_H
874
875