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