1
/*
2
 * Copyright (c) 1999
3
 * Silicon Graphics Computer Systems, Inc.
4
 *
5
 * Copyright (c) 1999
6
 * Boris Fomitchev
7
 *
8
 * This material is provided "as is", with absolutely no warranty expressed
9
 * or implied. Any use is at your own risk.
10
 *
11
 * Permission to use or copy this software for any purpose is hereby granted
12
 * without fee, provided the above notices are retained on all copies.
13
 * Permission to modify the code and to distribute modified code is granted,
14
 * provided the above notices are retained, and a notice that the code was
15
 * modified is included with the above copyright notice.
16
 *
17
 */
18
#include "stlport_prefix.h"
19
20
#include <vector>
21
22
#include <locale>
23
#include <istream>
24
25
#include <algorithm>
26
#include <functional>
27
28
#include "c_locale.h"
29
#include "locale_impl.h"
30
#include "acquire_release.h"
31
32
_STLP_BEGIN_NAMESPACE
33
34
//----------------------------------------------------------------------
35
// ctype_byname<char>
36
37
#if defined (__DMC__)
38
_STLP_DECLSPEC
39
#endif
40
ctype_byname<char>::ctype_byname(const char* name, size_t refs)
41
    : ctype<char>( 0, false, refs) {
42
  if (!name)
43
    locale::_M_throw_on_null_name();
44
45
  int __err_code;
46
  char buf[_Locale_MAX_SIMPLE_NAME];
47
  _M_ctype = _STLP_PRIV __acquire_ctype(name, buf, 0, &__err_code);
48
  if (!_M_ctype)
49
    locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
50
51
  _M_init();
52
}
53
54
void ctype_byname<char>::_M_init() {
55
  _M_ctype_table = _M_byname_table;
56
57
  // We have to do this, instead of just pointer twiddling, because
58
  // ctype_base::mask isn't the same type as _Locale_mask_t.
59
  const _Locale_mask_t* p = _Locale_ctype_table(_M_ctype);
60
  for (size_t i = 0; i != table_size; ++i) {
61
    _M_byname_table[i] = ctype_base::mask(p[i]);
62
  }
63
}
64
65
ctype_byname<char>::~ctype_byname()
66
{ _STLP_PRIV __release_ctype(_M_ctype); }
67
68
char ctype_byname<char>::do_toupper(char c) const
69
{ return (char)_Locale_toupper(_M_ctype, c); }
70
71
char ctype_byname<char>::do_tolower(char c) const
72
{ return (char)_Locale_tolower(_M_ctype, c); }
73
74
const char*
75
ctype_byname<char>::do_toupper(char* first, const char* last) const {
76
  for ( ; first != last ; ++first)
77
    *first = (char)_Locale_toupper(_M_ctype, *first);
78
  return last;
79
}
80
81
const char*
82
ctype_byname<char>::do_tolower(char* first, const char* last) const {
83
  for ( ; first != last ; ++first)
84
    *first = (char)_Locale_tolower(_M_ctype, *first);
85
  return last;
86
}
87
88
89
// Some helper functions used in ctype<>::scan_is and scan_is_not.
90
#if !defined (_STLP_NO_WCHAR_T)
91
92
_STLP_MOVE_TO_PRIV_NAMESPACE
93
94
// ctype_byname<wchar_t>
95
96
struct _Ctype_byname_w_is_mask : public unary_function<wchar_t, bool> {
97
  _Locale_mask_t M;
98
  _Locale_ctype* M_ctp;
99
100
  _Ctype_byname_w_is_mask(_Locale_mask_t m, _Locale_ctype* c)
101
    : M(m), M_ctp(c) {}
102
  bool operator()(wchar_t c) const
103
  { return _WLocale_ctype(M_ctp, c, M) != 0; }
104
};
105
106
_STLP_MOVE_TO_STD_NAMESPACE
107
108
#if defined (__DMC__)
109
_STLP_DECLSPEC
110
#endif
111
ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs)
112
  : ctype<wchar_t>(refs) {
113
  if (!name)
114
    locale::_M_throw_on_null_name();
115
116
  int __err_code;
117
  char buf[_Locale_MAX_SIMPLE_NAME];
118
  _M_ctype = _STLP_PRIV __acquire_ctype(name, buf, 0, &__err_code);
119
  if (!_M_ctype)
120
    locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
121
}
122
123
ctype_byname<wchar_t>::~ctype_byname()
124
{ _STLP_PRIV __release_ctype(_M_ctype); }
125
126
bool ctype_byname<wchar_t>::do_is(ctype_base::mask  m, wchar_t c) const
127
{ return _WLocale_ctype(_M_ctype, c, (_Locale_mask_t)m) != 0; }
128
129
const wchar_t*
130
ctype_byname<wchar_t>::do_is(const wchar_t* low, const wchar_t* high,
131
                             ctype_base::mask * m) const {
132
  _Locale_mask_t all_bits = _Locale_mask_t(ctype_base::space |
133
                                           ctype_base::print |
134
                                           ctype_base::cntrl |
135
                                           ctype_base::upper |
136
                                           ctype_base::lower |
137
                                           ctype_base::alpha |
138
                                           ctype_base::digit |
139
                                           ctype_base::punct |
140
                                           ctype_base::xdigit);
141
142
  for ( ; low < high; ++low, ++m)
143
    *m = ctype_base::mask (_WLocale_ctype(_M_ctype, *low, all_bits));
144
  return high;
145
}
146
147
const wchar_t*
148
ctype_byname<wchar_t>
149
  ::do_scan_is(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
150
{ return find_if(low, high, _STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype)); }
151
152
const wchar_t*
153
ctype_byname<wchar_t>
154
  ::do_scan_not(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
155
{ return find_if(low, high, not1(_STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype))); }
156
157
wchar_t ctype_byname<wchar_t>::do_toupper(wchar_t c) const
158
{ return _WLocale_toupper(_M_ctype, c); }
159
160
const wchar_t*
161
ctype_byname<wchar_t>::do_toupper(wchar_t* low, const wchar_t* high) const {
162
  for ( ; low < high; ++low)
163
    *low = _WLocale_toupper(_M_ctype, *low);
164
  return high;
165
}
166
167
wchar_t ctype_byname<wchar_t>::do_tolower(wchar_t c) const
168
{ return _WLocale_tolower(_M_ctype, c); }
169
170
const wchar_t*
171
ctype_byname<wchar_t>::do_tolower(wchar_t* low, const wchar_t* high) const {
172
  for ( ; low < high; ++low)
173
    *low = _WLocale_tolower(_M_ctype, *low);
174
  return high;
175
}
176
177
#endif /* WCHAR_T */
178
179
// collate_byname<char>
180
#if defined (__DMC__)
181
_STLP_DECLSPEC
182
#endif
183
collate_byname<char>::collate_byname(const char* name, size_t refs)
184
  : collate<char>(refs) {
185
  if (!name)
186
    locale::_M_throw_on_null_name();
187
188
  int __err_code;
189
  char buf[_Locale_MAX_SIMPLE_NAME];
190
  _M_collate = _STLP_PRIV __acquire_collate(name, buf, 0, &__err_code);
191
  if (!_M_collate)
192
    locale::_M_throw_on_creation_failure(__err_code, name, "collate");
193
}
194
195
collate_byname<char>::~collate_byname()
196
{ _STLP_PRIV __release_collate(_M_collate); }
197
198
int collate_byname<char>::do_compare(const char* __low1,
199
                                     const char* __high1,
200
                                     const char* __low2,
201
                                     const char* __high2) const {
202
  return _Locale_strcmp(_M_collate,
203
                        __low1, __high1 - __low1,
204
                        __low2, __high2 - __low2);
205
}
206
207
collate_byname<char>::string_type
208
collate_byname<char>::do_transform(const char* low, const char* high) const {
209
  if (low == high)
210
    return string_type();
211
212
  size_t n = _Locale_strxfrm(_M_collate, NULL, 0, low, high - low);
213
214
  // NOT PORTABLE.  What we're doing relies on internal details of the
215
  // string implementation.  (Contiguity of string elements and presence
216
  // of trailing zero.)
217
  string_type buf(n, 0);
218
  _Locale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
219
  return buf;
220
}
221
222
223
#if !defined (_STLP_NO_WCHAR_T)
224
225
// collate_byname<wchar_t>
226
227
#if defined (__DMC__)
228
_STLP_DECLSPEC
229
#endif
230
collate_byname<wchar_t>::collate_byname(const char* name, size_t refs)
231
  : collate<wchar_t>(refs) {
232
  if (!name)
233
    locale::_M_throw_on_null_name();
234
235
  int __err_code;
236
  char buf[_Locale_MAX_SIMPLE_NAME];
237
  _M_collate = _STLP_PRIV __acquire_collate(name, buf, 0, &__err_code);
238
  if (!_M_collate)
239
    locale::_M_throw_on_creation_failure(__err_code, name, "collate");
240
}
241
242
collate_byname<wchar_t>::~collate_byname()
243
{ _STLP_PRIV __release_collate(_M_collate); }
244
245
int collate_byname<wchar_t>::do_compare(const wchar_t* low1,
246
                                        const wchar_t* high1,
247
                                        const wchar_t* low2,
248
                                        const wchar_t* high2) const {
249
  return _WLocale_strcmp(_M_collate,
250
                         low1, high1 - low1,
251
                         low2, high2 - low2);
252
}
253
254
collate_byname<wchar_t>::string_type
255
collate_byname<wchar_t>::do_transform(const wchar_t* low,
256
                                      const wchar_t* high) const {
257
  if (low == high)
258
    return string_type();
259
260
  size_t n = _WLocale_strxfrm(_M_collate, NULL, 0, low, high - low);
261
262
  // NOT PORTABLE.  What we're doing relies on internal details of the
263
  // string implementation.  (Contiguity of string elements and presence
264
  // of trailing zero.)
265
  string_type buf(n, 0);
266
  _WLocale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
267
  return buf;
268
}
269
270
#endif /*  _STLP_NO_WCHAR_T */
271
272
//----------------------------------------------------------------------
273
// codecvt_byname<char>
274
275
codecvt_byname<char, char, mbstate_t>
276
  ::codecvt_byname(const char* name, size_t refs)
277
    : codecvt<char, char, mbstate_t>(refs) {
278
  if (!name)
279
    locale::_M_throw_on_null_name();
280
}
281
282
codecvt_byname<char, char, mbstate_t>::~codecvt_byname() {}
283
284
285
#if !defined (_STLP_NO_WCHAR_T)
286
287
//----------------------------------------------------------------------
288
// codecvt_byname<wchar_t>
289
codecvt_byname<wchar_t, char, mbstate_t>::codecvt_byname(const char* name, size_t refs)
290
  : codecvt<wchar_t, char, mbstate_t>(refs) {
291
  if (!name)
292
    locale::_M_throw_on_null_name();
293
294
  int __err_code;
295
  char buf[_Locale_MAX_SIMPLE_NAME];
296
  _M_codecvt = _STLP_PRIV __acquire_codecvt(name, buf, 0, &__err_code);
297
  if (!_M_codecvt)
298
    locale::_M_throw_on_creation_failure(__err_code, name, "ctype");
299
}
300
301
codecvt_byname<wchar_t, char, mbstate_t>::~codecvt_byname()
302
{ _STLP_PRIV __release_codecvt(_M_codecvt); }
303
304
codecvt<wchar_t, char, mbstate_t>::result
305
codecvt_byname<wchar_t, char, mbstate_t>::do_out(state_type&         state,
306
                                                 const wchar_t*  from,
307
                                                 const wchar_t*  from_end,
308
                                                 const wchar_t*& from_next,
309
                                                 char*        to,
310
                                                 char*        to_limit,
311
                                                 char*&       to_next) const {
312
  while (from != from_end && to != to_limit) {
313
    size_t chars_stored = _WLocale_wctomb(_M_codecvt,
314
                                          to, to_limit - to, *from,
315
                                          &state);
316
    if (chars_stored == (size_t) -1) {
317
      from_next = from;
318
      to_next   = to;
319
      return error;
320
    }
321
    else if (chars_stored == (size_t) -2) {
322
      from_next = from;
323
      to_next   = to;
324
      return partial;
325
    }
326
327
    ++from;
328
    to += chars_stored;
329
  }
330
331
  from_next = from;
332
  to_next   = to;
333
  return ok;
334
}
335
336
codecvt<wchar_t, char, mbstate_t>::result
337
codecvt_byname<wchar_t, char, mbstate_t>::do_in(state_type&         state,
338
                                                const char*  from,
339
                                                const char*  from_end,
340
                                                const char*& from_next,
341
                                                wchar_t*        to,
342
                                                wchar_t*        to_end,
343
                                                wchar_t*&       to_next) const {
344
  while (from != from_end && to != to_end) {
345
    size_t chars_read = _WLocale_mbtowc(_M_codecvt,
346
                                        to, from, from_end - from,
347
                                        &state);
348
    if (chars_read == (size_t) -1) {
349
      from_next = from;
350
      to_next   = to;
351
      return error;
352
    }
353
354
    if (chars_read == (size_t) -2) {
355
      from_next = from;
356
      to_next   = to;
357
      return partial;
358
    }
359
360
    from += chars_read;
361
    to++;
362
  }
363
364
  from_next = from;
365
  to_next   = to;
366
  return ok;
367
}
368
369
codecvt<wchar_t, char, mbstate_t>::result
370
codecvt_byname<wchar_t, char, mbstate_t>::do_unshift(state_type&   state,
371
                                                     char*  to,
372
                                                     char*  to_limit,
373
                                                     char*& to_next) const {
374
  to_next = to;
375
  size_t result = _WLocale_unshift(_M_codecvt, &state,
376
                                   to, to_limit - to, &to_next);
377
  if (result == (size_t) -1)
378
    return error;
379
  else if (result == (size_t) -2)
380
    return partial;
381
  else
382
#    if defined (__ISCPP__)
383
    return /*to_next == to ? noconv :*/ ok;
384
#    else
385
    return to_next == to ? noconv : ok;
386
#    endif
387
}
388
389
int
390
codecvt_byname<wchar_t, char, mbstate_t>::do_encoding() const _STLP_NOTHROW {
391
  if (_WLocale_is_stateless(_M_codecvt)) {
392
    int max_width = _WLocale_mb_cur_max(_M_codecvt);
393
    int min_width = _WLocale_mb_cur_min(_M_codecvt);
394
    return min_width == max_width ? min_width : 0;
395
  }
396
  else
397
    return -1;
398
}
399
400
bool
401
codecvt_byname<wchar_t, char, mbstate_t>::do_always_noconv() const _STLP_NOTHROW
402
{ return false; }
403
404
int
405
codecvt_byname<wchar_t, char, mbstate_t>::do_length(state_type&         state,
406
                                                    const  char* from,
407
                                                    const  char* end,
408
                                                    size_t              mx) const {
409
  size_t __count = 0;
410
  while (from != end && mx--) {
411
    intern_type __dummy;
412
    size_t chars_read = _WLocale_mbtowc(_M_codecvt,
413
                                        &__dummy, from, end - from,
414
                                        &state);
415
    if ((chars_read == (size_t) -1) || (chars_read == (size_t) -2)) // error or partial
416
      break;
417
    __count += chars_read;
418
    from += chars_read;
419
  }
420
  return int(__count); 
421
}
422
423
int
424
codecvt_byname<wchar_t, char, mbstate_t>::do_max_length() const _STLP_NOTHROW
425
{ return _WLocale_mb_cur_max(_M_codecvt); }
426
#endif
427
428
// numpunct_byname<char>
429
numpunct_byname<char>::numpunct_byname(const char* name, size_t refs)
430
: numpunct<char>(refs) {
431
  if (!name)
432
    locale::_M_throw_on_null_name();
433
434
  int __err_code;
435
  char buf[_Locale_MAX_SIMPLE_NAME];
436
  _M_numeric = _STLP_PRIV __acquire_numeric(name, buf, 0, &__err_code);
437
  if (!_M_numeric)
438
    locale::_M_throw_on_creation_failure(__err_code, name, "numpunct");
439
}
440
441
numpunct_byname<char>::~numpunct_byname()
442
{ _STLP_PRIV __release_numeric(_M_numeric); }
443
444
char numpunct_byname<char>::do_decimal_point() const
445
{ return _Locale_decimal_point(_M_numeric); }
446
447
char numpunct_byname<char>::do_thousands_sep() const
448
{ return _Locale_thousands_sep(_M_numeric); }
449
450
string numpunct_byname<char>::do_grouping() const {
451
  const char * __grouping = _Locale_grouping(_M_numeric);
452
  if (__grouping != NULL && __grouping[0] == CHAR_MAX)
453
    __grouping = "";
454
  return __grouping;
455
}
456
457
string numpunct_byname<char>::do_truename() const
458
{ return _Locale_true(_M_numeric); }
459
460
string numpunct_byname<char>::do_falsename() const
461
{ return _Locale_false(_M_numeric); }
462
463
//----------------------------------------------------------------------
464
// numpunct<wchar_t>
465
466
#if !defined (_STLP_NO_WCHAR_T)
467
468
// numpunct_byname<wchar_t>
469
470
numpunct_byname<wchar_t>::numpunct_byname(const char* name, size_t refs)
471
: numpunct<wchar_t>(refs) {
472
  if (!name)
473
    locale::_M_throw_on_null_name();
474
475
  int __err_code;
476
  char buf[_Locale_MAX_SIMPLE_NAME];
477
  _M_numeric = _STLP_PRIV __acquire_numeric(name, buf, 0, &__err_code);
478
  if (!_M_numeric)
479
    locale::_M_throw_on_creation_failure(__err_code, name, "numpunct");
480
}
481
482
numpunct_byname<wchar_t>::~numpunct_byname()
483
{ _STLP_PRIV __release_numeric(_M_numeric); }
484
485
wchar_t numpunct_byname<wchar_t>::do_decimal_point() const
486
{ return _WLocale_decimal_point(_M_numeric); }
487
488
wchar_t numpunct_byname<wchar_t>::do_thousands_sep() const
489
{ return _WLocale_thousands_sep(_M_numeric); }
490
491
string numpunct_byname<wchar_t>::do_grouping() const {
492
  const char * __grouping = _Locale_grouping(_M_numeric);
493
  if (__grouping != NULL && __grouping[0] == CHAR_MAX)
494
    __grouping = "";
495
  return __grouping;
496
}
497
498
wstring numpunct_byname<wchar_t>::do_truename() const {
499
  wchar_t buf[16];
500
  return _WLocale_true(_M_numeric, _STLP_ARRAY_AND_SIZE(buf));
501
}
502
503
wstring numpunct_byname<wchar_t>::do_falsename() const {
504
  wchar_t buf[16];
505
  return _WLocale_false(_M_numeric, _STLP_ARRAY_AND_SIZE(buf));
506
}
507
508
#endif
509
510
_STLP_MOVE_TO_PRIV_NAMESPACE
511
512
static void _Init_monetary_formats(money_base::pattern& pos_format,
513
                                   money_base::pattern& neg_format,
514
                                   _Locale_monetary * monetary) {
515
  switch (_Locale_p_sign_posn(monetary)) {
516
    case 0: // Parentheses surround the quantity and currency symbol
517
    case 1: // The sign string precedes the quantity and currency symbol
518
      pos_format.field[0] = (char) money_base::sign;
519
      if (_Locale_p_cs_precedes(monetary)) {
520
        // 1 if currency symbol precedes a positive value
521
        pos_format.field[1] = (char) money_base::symbol;
522
        if (_Locale_p_sep_by_space(monetary)) {
523
          // a space separates currency symbol from a positive value.
524
          pos_format.field[2] = (char) money_base::space;
525
          pos_format.field[3] = (char) money_base::value;
526
        } else {
527
          // a space not separates currency symbol from a positive value.
528
          pos_format.field[2] = (char) money_base::value;
529
          pos_format.field[3] = (char) money_base::none;
530
        }
531
      } else {
532
        // 0 if currency symbol succeeds a positive value
533
        pos_format.field[1] = (char) money_base::value;
534
        if (_Locale_p_sep_by_space(monetary)) {
535
          // a space separates currency symbol from a positive value.
536
          pos_format.field[2] = (char) money_base::space;
537
          pos_format.field[3] = (char) money_base::symbol;
538
        } else {
539
          // a space not separates currency symbol from a positive value.
540
          pos_format.field[2] = (char) money_base::symbol;
541
          pos_format.field[3] = (char) money_base::none;
542
        }
543
      }
544
      break;
545
    case 2: // The sign string succeeds the quantity and currency symbol.
546
      if (_Locale_p_cs_precedes(monetary)) {
547
        // 1 if currency symbol precedes a positive value
548
        pos_format.field[0] = (char) money_base::symbol;
549
        if (_Locale_p_sep_by_space(monetary)) {
550
          // a space separates currency symbol from a positive value.
551
          pos_format.field[1] = (char) money_base::space;
552
          pos_format.field[2] = (char) money_base::value;
553
          pos_format.field[3] = (char) money_base::sign;
554
        } else {
555
          // a space not separates currency symbol from a positive value.
556
          pos_format.field[1] = (char) money_base::value;
557
          pos_format.field[2] = (char) money_base::sign;
558
          pos_format.field[3] = (char) money_base::none;
559
        }
560
      } else {
561
        // 0 if currency symbol succeeds a positive value
562
        pos_format.field[0] = (char) money_base::value;
563
        if (_Locale_p_sep_by_space(monetary)) {
564
          // a space separates currency symbol from a positive value.
565
          pos_format.field[1] = (char) money_base::space;
566
          pos_format.field[2] = (char) money_base::symbol;
567
          pos_format.field[3] = (char) money_base::sign;
568
        } else {
569
          // a space not separates currency symbol from a positive value.
570
          pos_format.field[1] = (char) money_base::symbol;
571
          pos_format.field[2] = (char) money_base::sign;
572
          pos_format.field[3] = (char) money_base::none;
573
        }
574
      }
575
      break;
576
    case 3: // The sign string immediately precedes the currency symbol.
577
      if (_Locale_p_cs_precedes(monetary)) {
578
        // 1 if currency symbol precedes a positive value
579
        pos_format.field[0] = (char) money_base::sign;
580
        pos_format.field[1] = (char) money_base::symbol;
581
        if (_Locale_p_sep_by_space(monetary)) {
582
          // a space separates currency symbol from a positive value.
583
          pos_format.field[2] = (char) money_base::space;
584
          pos_format.field[3] = (char) money_base::value;
585
        } else {
586
          // a space not separates currency symbol from a positive value.
587
          pos_format.field[2] = (char) money_base::value;
588
          pos_format.field[3] = (char) money_base::none;
589
        }
590
      } else {
591
        // 0 if currency symbol succeeds a positive value
592
        pos_format.field[0] = (char) money_base::value;
593
        pos_format.field[1] = (char) money_base::sign;
594
        pos_format.field[2] = (char) money_base::symbol;
595
        pos_format.field[3] = (char) money_base::none;
596
      }
597
      break;
598
    case 4: // The sign string immediately succeeds the currency symbol.
599
      if (_Locale_p_cs_precedes(monetary)) {
600
        // 1 if currency symbol precedes a positive value
601
        pos_format.field[0] = (char) money_base::symbol;
602
        pos_format.field[1] = (char) money_base::sign;
603
        pos_format.field[2] = (char) money_base::value;
604
        pos_format.field[3] = (char) money_base::none;
605
      } else {
606
        // 0 if currency symbol succeeds a positive value
607
        pos_format.field[0] = (char) money_base::value;
608
        if (_Locale_p_sep_by_space(monetary)) {
609
          // a space separates currency symbol from a positive value.
610
          pos_format.field[1] = (char) money_base::space;
611
          pos_format.field[2] = (char) money_base::symbol;
612
          pos_format.field[3] = (char) money_base::sign;
613
        } else {
614
          // a space not separates currency symbol from a positive value.
615
          pos_format.field[1] = (char) money_base::symbol;
616
          pos_format.field[2] = (char) money_base::sign;
617
          pos_format.field[3] = (char) money_base::none;
618
        }
619
      }
620
      break;
621
    default: // Default C++ Standard format
622
      pos_format.field[0] = (char) money_base::symbol;
623
      pos_format.field[1] = (char) money_base::sign;
624
      pos_format.field[2] = (char) money_base::none;
625
      pos_format.field[3] = (char) money_base::value;
626
      break;
627
  }
628
629
  switch (_Locale_n_sign_posn(monetary)) {
630
    case 0: // Parentheses surround the quantity and currency symbol
631
    case 1: // The sign string precedes the quantity and currency symbol
632
      neg_format.field[0] = (char) money_base::sign;
633
      if (_Locale_n_cs_precedes(monetary)) {
634
        // 1 if currency symbol precedes a negative value
635
        neg_format.field[1] = (char) money_base::symbol;
636
        if (_Locale_n_sep_by_space(monetary)) {
637
          // a space separates currency symbol from a negative value.
638
          neg_format.field[2] = (char) money_base::space;
639
          neg_format.field[3] = (char) money_base::value;
640
        } else {
641
          // a space not separates currency symbol from a negative value.
642
          neg_format.field[2] = (char) money_base::value;
643
          neg_format.field[3] = (char) money_base::none;
644
        }
645
      } else {
646
        // 0 if currency symbol succeeds a negative value
647
        neg_format.field[1] = (char) money_base::value;
648
        if (_Locale_n_sep_by_space(monetary)) {
649
          // a space separates currency symbol from a negative value.
650
          neg_format.field[2] = (char) money_base::space;
651
          neg_format.field[3] = (char) money_base::symbol;
652
        } else {
653
          // a space not separates currency symbol from a negative value.
654
          neg_format.field[2] = (char) money_base::symbol;
655
          neg_format.field[3] = (char) money_base::none;
656
        }
657
      }
658
      break;
659
    case 2: // The sign string succeeds the quantity and currency symbol.
660
      if (_Locale_n_cs_precedes(monetary)) {
661
        // 1 if currency symbol precedes a negative value
662
        neg_format.field[0] = (char) money_base::symbol;
663
        if (_Locale_n_sep_by_space(monetary)) {
664
          // a space separates currency symbol from a negative value.
665
          neg_format.field[1] = (char) money_base::space;
666
          neg_format.field[2] = (char) money_base::value;
667
          neg_format.field[3] = (char) money_base::sign;
668
        } else {
669
          // a space not separates currency symbol from a negative value.
670
          neg_format.field[1] = (char) money_base::value;
671
          neg_format.field[2] = (char) money_base::sign;
672
          neg_format.field[3] = (char) money_base::none;
673
        }
674
      } else {
675
        // 0 if currency symbol succeeds a negative value
676
        neg_format.field[0] = (char) money_base::value;
677
        if (_Locale_n_sep_by_space(monetary)) {
678
          // a space separates currency symbol from a negative value.
679
          neg_format.field[1] = (char) money_base::space;
680
          neg_format.field[2] = (char) money_base::symbol;
681
          neg_format.field[3] = (char) money_base::sign;
682
        } else {
683
          // a space not separates currency symbol from a negative value.
684
          neg_format.field[1] = (char) money_base::symbol;
685
          neg_format.field[2] = (char) money_base::sign;
686
          neg_format.field[3] = (char) money_base::none;
687
        }
688
      }
689
      break;
690
    case 3: // The sign string immediately precedes the currency symbol.
691
      if (_Locale_n_cs_precedes(monetary)) {
692
        // 1 if currency symbol precedes a negative value
693
        neg_format.field[0] = (char) money_base::sign;
694
        neg_format.field[1] = (char) money_base::symbol;
695
        if (_Locale_n_sep_by_space(monetary)) {
696
          // a space separates currency symbol from a negative value.
697
          neg_format.field[2] = (char) money_base::space;
698
          neg_format.field[3] = (char) money_base::value;
699
        } else {
700
          // a space not separates currency symbol from a negative value.
701
          neg_format.field[2] = (char) money_base::value;
702
          neg_format.field[3] = (char) money_base::none;
703
        }
704
      } else {
705
        // 0 if currency symbol succeeds a negative value
706
        neg_format.field[0] = (char) money_base::value;
707
        neg_format.field[1] = (char) money_base::sign;
708
        neg_format.field[2] = (char) money_base::symbol;
709
        neg_format.field[3] = (char) money_base::none;
710
      }
711
      break;
712
    case 4: // The sign string immediately succeeds the currency symbol.
713
      if (_Locale_n_cs_precedes(monetary)) {
714
        // 1 if currency symbol precedes a negative value
715
        neg_format.field[0] = (char) money_base::symbol;
716
        neg_format.field[1] = (char) money_base::sign;
717
        neg_format.field[2] = (char) money_base::none;
718
        neg_format.field[3] = (char) money_base::value;
719
      } else {
720
        // 0 if currency symbol succeeds a negative value
721
        neg_format.field[0] = (char) money_base::value;
722
        if (_Locale_n_sep_by_space(monetary)) {
723
          // a space separates currency symbol from a negative value.
724
          neg_format.field[1] = (char) money_base::space;
725
          neg_format.field[2] = (char) money_base::symbol;
726
          neg_format.field[3] = (char) money_base::sign;
727
        } else {
728
          // a space not separates currency symbol from a negative value.
729
          neg_format.field[1] = (char) money_base::symbol;
730
          neg_format.field[2] = (char) money_base::sign;
731
          neg_format.field[3] = (char) money_base::none;
732
        }
733
      }
734
      break;
735
    default: // Default C++ Standard format
736
      neg_format.field[0] = (char) money_base::symbol;
737
      neg_format.field[1] = (char) money_base::sign;
738
      neg_format.field[2] = (char) money_base::none;
739
      neg_format.field[3] = (char) money_base::value;
740
      break;
741
  }
742
}
743
744
// international variant of monetary
745
746
/*
747
 * int_curr_symbol
748
 *
749
 *   The international currency symbol. The operand is a four-character
750
 *   string, with the first three characters containing the alphabetic
751
 *   international currency symbol in accordance with those specified
752
 *   in the ISO 4217 specification. The fourth character is the character used
753
 *   to separate the international currency symbol from the monetary quantity.
754
 *
755
 * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html)
756
 */
757
758
/*
759
 * Standards are unclear in the usage of international currency
760
 * and monetary formats.
761
 * But I am expect that international currency symbol should be the first
762
 * (not depends upon where currency symbol situated in the national
763
 * format).
764
 *
765
 * If this isn't so, let's see:
766
 *       1 234.56 RUR
767
 *       GBP 1,234.56
768
 *       USD 1,234.56
769
 * The situation really is worse than you see above:
770
 * RUR typed wrong here---it prints '1 234.56 RUR ' (see space after RUR).
771
 * This is due to intl_fmp.curr_symbol() == "RUR ". (see reference in comments
772
 * above).
773
 *
774
 */
775
776
static void _Init_monetary_formats_int(money_base::pattern& pos_format,
777
                                       money_base::pattern& neg_format,
778
                                       _Locale_monetary * monetary)
779
{
780
781
  switch (_Locale_p_sign_posn(monetary)) {
782
    case 0: // Parentheses surround the quantity and currency symbol
783
    case 1: // The sign string precedes the quantity and currency symbol
784
      pos_format.field[0] = (char) money_base::symbol;
785
      pos_format.field[1] = (char) money_base::sign;
786
      pos_format.field[2] = (char) money_base::value;
787
      pos_format.field[3] = (char) money_base::none;
788
      break;
789
    case 2: // The sign string succeeds the quantity and currency symbol.
790
      pos_format.field[0] = (char) money_base::symbol;
791
      pos_format.field[1] = (char) money_base::value;
792
      pos_format.field[2] = (char) money_base::sign;
793
      pos_format.field[3] = (char) money_base::none;
794
      break;
795
    case 3: // The sign string immediately precedes the currency symbol.
796
    case 4: // The sign string immediately succeeds the currency symbol.
797
      pos_format.field[0] = (char) money_base::symbol;
798
      if (_Locale_p_cs_precedes(monetary)) {
799
        // 1 if currency symbol precedes a positive value
800
        pos_format.field[1] = (char) money_base::sign;
801
        pos_format.field[2] = (char) money_base::value;
802
      } else {
803
        // 0 if currency symbol succeeds a positive value
804
        pos_format.field[1] = (char) money_base::value;
805
        pos_format.field[2] = (char) money_base::sign;
806
      }
807
      pos_format.field[3] = (char) money_base::none;
808
      break;
809
    default: // Default C++ Standard format
810
      pos_format.field[0] = (char) money_base::symbol;
811
      pos_format.field[1] = (char) money_base::sign;
812
      pos_format.field[2] = (char) money_base::none;
813
      pos_format.field[3] = (char) money_base::value;
814
      break;
815
  }
816
817
818
  switch (_Locale_n_sign_posn(monetary)) {
819
    case 0: // Parentheses surround the quantity and currency symbol
820
    case 1: // The sign string precedes the quantity and currency symbol
821
      neg_format.field[0] = (char) money_base::symbol;
822
      neg_format.field[1] = (char) money_base::sign;
823
      neg_format.field[2] = (char) money_base::value;
824
      neg_format.field[3] = (char) money_base::none;
825
      break;
826
    case 2: // The sign string succeeds the quantity and currency symbol.
827
      neg_format.field[0] = (char) money_base::symbol;
828
      neg_format.field[1] = (char) money_base::value;
829
      neg_format.field[2] = (char) money_base::sign;
830
      neg_format.field[3] = (char) money_base::none;
831
      break;
832
    case 3: // The sign string immediately precedes the currency symbol.
833
    case 4: // The sign string immediately succeeds the currency symbol.
834
      neg_format.field[0] = (char) money_base::symbol;
835
      if (_Locale_n_cs_precedes(monetary)) {
836
        // 1 if currency symbol precedes a negative value
837
        neg_format.field[1] = (char) money_base::sign;
838
        neg_format.field[2] = (char) money_base::value;
839
      } else {
840
        // 0 if currency symbol succeeds a negative value
841
        neg_format.field[1] = (char) money_base::value;
842
        neg_format.field[2] = (char) money_base::sign;
843
      }
844
      neg_format.field[3] = (char) money_base::none;
845
      break;
846
    default: // Default C++ Standard format
847
      neg_format.field[0] = (char) money_base::symbol;
848
      neg_format.field[1] = (char) money_base::sign;
849
      neg_format.field[2] = (char) money_base::none;
850
      neg_format.field[3] = (char) money_base::value;
851
      break;
852
  }
853
}
854
855
_STLP_MOVE_TO_STD_NAMESPACE
856
857
//
858
// moneypunct_byname<>
859
//
860
moneypunct_byname<char, true>::moneypunct_byname(const char * name,
861
                                                 size_t refs)
862
    : moneypunct<char, true>(refs) {
863
  if (!name)
864
    locale::_M_throw_on_null_name();
865
866
  int __err_code;
867
  char buf[_Locale_MAX_SIMPLE_NAME];
868
  _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
869
  if (!_M_monetary)
870
    locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
871
872
  _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
873
}
874
875
moneypunct_byname<char, true>::moneypunct_byname(_Locale_monetary *__mon)
876
  : _M_monetary(__mon) {
877
  _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
878
}
879
880
moneypunct_byname<char, true>::~moneypunct_byname()
881
{ _STLP_PRIV __release_monetary(_M_monetary); }
882
883
char moneypunct_byname<char, true>::do_decimal_point() const
884
{ return _Locale_mon_decimal_point(_M_monetary); }
885
886
char moneypunct_byname<char, true>::do_thousands_sep() const
887
{ return _Locale_mon_thousands_sep(_M_monetary); }
888
889
string moneypunct_byname<char, true>::do_grouping() const
890
{ return _Locale_mon_grouping(_M_monetary); }
891
892
string moneypunct_byname<char, true>::do_curr_symbol() const
893
{ return _Locale_int_curr_symbol(_M_monetary); }
894
895
string moneypunct_byname<char, true>::do_positive_sign() const
896
{ return _Locale_positive_sign(_M_monetary); }
897
898
string moneypunct_byname<char, true>::do_negative_sign() const
899
{ return _Locale_negative_sign(_M_monetary); }
900
901
int moneypunct_byname<char, true>::do_frac_digits() const
902
{ return _Locale_int_frac_digits(_M_monetary); }
903
904
moneypunct_byname<char, false>::moneypunct_byname(const char * name,
905
                                                  size_t refs)
906
    : moneypunct<char, false>(refs) {
907
  if (!name)
908
    locale::_M_throw_on_null_name();
909
910
  int __err_code;
911
  char buf[_Locale_MAX_SIMPLE_NAME];
912
  _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
913
  if (!_M_monetary)
914
    locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
915
916
  _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
917
}
918
919
moneypunct_byname<char, false>::moneypunct_byname(_Locale_monetary *__mon)
920
  : _M_monetary(__mon) {
921
  _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
922
}
923
924
moneypunct_byname<char, false>::~moneypunct_byname()
925
{ _STLP_PRIV __release_monetary(_M_monetary); }
926
927
char moneypunct_byname<char, false>::do_decimal_point() const
928
{ return _Locale_mon_decimal_point(_M_monetary); }
929
930
char moneypunct_byname<char, false>::do_thousands_sep() const
931
{ return _Locale_mon_thousands_sep(_M_monetary); }
932
933
string moneypunct_byname<char, false>::do_grouping() const
934
{ return _Locale_mon_grouping(_M_monetary); }
935
936
string moneypunct_byname<char, false>::do_curr_symbol() const
937
{ return _Locale_currency_symbol(_M_monetary); }
938
939
string moneypunct_byname<char, false>::do_positive_sign() const
940
{ return _Locale_positive_sign(_M_monetary); }
941
942
string moneypunct_byname<char, false>::do_negative_sign() const
943
{ return _Locale_negative_sign(_M_monetary); }
944
945
int moneypunct_byname<char, false>::do_frac_digits() const
946
{ return _Locale_frac_digits(_M_monetary); }
947
948
//
949
// moneypunct_byname<wchar_t>
950
//
951
#if !defined (_STLP_NO_WCHAR_T)
952
953
moneypunct_byname<wchar_t, true>::moneypunct_byname(const char * name,
954
                                                    size_t refs)
955
    : moneypunct<wchar_t, true>(refs) {
956
  if (!name)
957
    locale::_M_throw_on_null_name();
958
959
  int __err_code;
960
  char buf[_Locale_MAX_SIMPLE_NAME];
961
  _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
962
  if (!_M_monetary)
963
    locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
964
965
  _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
966
}
967
968
moneypunct_byname<wchar_t, true>::moneypunct_byname(_Locale_monetary *__mon)
969
  : _M_monetary(__mon) {
970
  _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
971
}
972
973
moneypunct_byname<wchar_t, true>::~moneypunct_byname()
974
{ _STLP_PRIV __release_monetary(_M_monetary); }
975
976
wchar_t moneypunct_byname<wchar_t, true>::do_decimal_point() const
977
{ return _Locale_mon_decimal_point(_M_monetary); }
978
979
wchar_t moneypunct_byname<wchar_t, true>::do_thousands_sep() const
980
{ return _Locale_mon_thousands_sep(_M_monetary); }
981
982
string moneypunct_byname<wchar_t, true>::do_grouping() const
983
{ return _Locale_mon_grouping(_M_monetary); }
984
985
inline wstring __do_widen (string const& str) {
986
#if defined (_STLP_MSVC)
987
  wstring::_Reserve_t __Reserve;
988
  size_t __size = str.size();
989
  wstring result(__Reserve, __size);
990
  copy(str.begin(), str.end(), result.begin());
991
#else
992
  wstring result(str.begin(), str.end());
993
#endif
994
  return result;
995
}
996
997
wstring moneypunct_byname<wchar_t, true>::do_curr_symbol() const
998
{ wchar_t buf[16]; return _WLocale_int_curr_symbol(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
999
1000
wstring moneypunct_byname<wchar_t, true>::do_positive_sign() const
1001
{ wchar_t buf[16]; return _WLocale_positive_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
1002
1003
wstring moneypunct_byname<wchar_t, true>::do_negative_sign() const
1004
{ wchar_t buf[16]; return _WLocale_negative_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
1005
1006
int moneypunct_byname<wchar_t, true>::do_frac_digits() const
1007
{ return _Locale_int_frac_digits(_M_monetary); }
1008
1009
moneypunct_byname<wchar_t, false>::moneypunct_byname(const char * name,
1010
                                                     size_t refs)
1011
    : moneypunct<wchar_t, false>(refs) {
1012
  if (!name)
1013
    locale::_M_throw_on_null_name() ;
1014
1015
  int __err_code;
1016
  char buf[_Locale_MAX_SIMPLE_NAME];
1017
  _M_monetary = _STLP_PRIV __acquire_monetary(name, buf, 0, &__err_code);
1018
  if (!_M_monetary)
1019
    locale::_M_throw_on_creation_failure(__err_code, name, "moneypunct");
1020
1021
  _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
1022
}
1023
1024
moneypunct_byname<wchar_t, false>::moneypunct_byname(_Locale_monetary *__mon)
1025
  : _M_monetary(__mon) {
1026
  _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
1027
}
1028
1029
moneypunct_byname<wchar_t, false>::~moneypunct_byname()
1030
{ _STLP_PRIV __release_monetary(_M_monetary); }
1031
1032
wchar_t moneypunct_byname<wchar_t, false>::do_decimal_point() const
1033
{ return _Locale_mon_decimal_point(_M_monetary); }
1034
1035
wchar_t moneypunct_byname<wchar_t, false>::do_thousands_sep() const
1036
{ return _Locale_mon_thousands_sep(_M_monetary); }
1037
1038
string moneypunct_byname<wchar_t, false>::do_grouping() const
1039
{ return _Locale_mon_grouping(_M_monetary); }
1040
1041
wstring moneypunct_byname<wchar_t, false>::do_curr_symbol() const
1042
{ wchar_t buf[16]; return _WLocale_currency_symbol(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
1043
1044
wstring moneypunct_byname<wchar_t, false>::do_positive_sign() const
1045
{ wchar_t buf[16]; return _WLocale_positive_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
1046
1047
wstring moneypunct_byname<wchar_t, false>::do_negative_sign() const
1048
{ wchar_t buf[16]; return _WLocale_negative_sign(_M_monetary, _STLP_ARRAY_AND_SIZE(buf)); }
1049
1050
int moneypunct_byname<wchar_t, false>::do_frac_digits() const
1051
{ return _Locale_frac_digits(_M_monetary); }
1052
1053
#endif
1054
1055
_STLP_END_NAMESPACE