]> git.buserror.net Git - polintos/scott/priv.git/blob - lib/c++/stlport/facets_byname.cpp
Add STLport 5.1.4
[polintos/scott/priv.git] / lib / c++ / stlport / facets_byname.cpp
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 ctype_byname<char>::ctype_byname(const char* name, size_t refs, _Locale_name_hint* hint) :
39     ctype<char>( 0, false, refs),
40     _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
41   ctype<char>::_M_ctype_table = _M_byname_table;
42   if (!_M_ctype)
43     locale::_M_throw_runtime_error();
44
45   // We have to do this, instead of just pointer twiddling, because
46   // ctype_base::mask isn't the same type as _Locale_mask_t.
47
48   const _Locale_mask_t* p = _Locale_ctype_table(_M_ctype);
49
50   if (!p)
51     locale::_M_throw_runtime_error();
52
53   for (size_t i = 0; i < table_size; ++i) {
54     _Locale_mask_t __m = p[i];
55     if (__m & (upper | lower))
56       __m |= alpha;
57     _M_byname_table[i] = ctype_base::mask(__m);
58   }
59 }
60
61 ctype_byname<char>::~ctype_byname()
62 { _STLP_PRIV __release_ctype(_M_ctype); }
63
64 char ctype_byname<char>::do_toupper(char c) const
65 { return (char)_Locale_toupper(_M_ctype, c); }
66
67 char ctype_byname<char>::do_tolower(char c) const
68 { return (char)_Locale_tolower(_M_ctype, c); }
69
70 const char*
71 ctype_byname<char>::do_toupper(char* first, const char* last) const {
72   for ( ; first != last ; ++first)
73     *first = (char)_Locale_toupper(_M_ctype, *first);
74   return last;
75 }
76
77 const char*
78 ctype_byname<char>::do_tolower(char* first, const char* last) const {
79   for ( ; first != last ; ++first)
80     *first = (char)_Locale_tolower(_M_ctype, *first);
81   return last;
82 }
83
84
85 // Some helper functions used in ctype<>::scan_is and scan_is_not.
86 #if !defined (_STLP_NO_WCHAR_T)
87
88 _STLP_MOVE_TO_PRIV_NAMESPACE
89
90 // ctype_byname<wchar_t>
91
92 struct _Ctype_byname_w_is_mask {
93   typedef wchar_t argument_type;
94   typedef bool    result_type;
95
96   /* ctype_base::mask*/ int  M;
97   _Locale_ctype* M_ctp;
98
99   _Ctype_byname_w_is_mask(/* ctype_base::mask */ int m, _Locale_ctype* c) : M((int)m), M_ctp(c) {}
100   bool operator()(wchar_t c) const
101     { return (M & _Locale_wchar_ctype(M_ctp, c, M)) != 0; }
102 };
103
104 _STLP_MOVE_TO_STD_NAMESPACE
105
106 ctype_byname<wchar_t>::ctype_byname(const char* name, size_t refs, _Locale_name_hint* hint)
107   : ctype<wchar_t>(refs),
108     _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
109   if (!_M_ctype)
110     locale::_M_throw_runtime_error();
111 }
112
113 ctype_byname<wchar_t>::~ctype_byname()
114 { _STLP_PRIV __release_ctype(_M_ctype); }
115
116 bool ctype_byname<wchar_t>::do_is(ctype_base::mask  m, wchar_t c) const
117 { return (m & _Locale_wchar_ctype(_M_ctype, c, m)) != 0; }
118
119 const wchar_t*
120 ctype_byname<wchar_t>::do_is(const wchar_t* low, const wchar_t* high,
121                              ctype_base::mask * m) const {
122   ctype_base::mask all_bits = ctype_base::mask(
123     ctype_base::space |
124     ctype_base::print |
125     ctype_base::cntrl |
126     ctype_base::upper |
127     ctype_base::lower |
128     ctype_base::alpha |
129     ctype_base::digit |
130     ctype_base::punct |
131     ctype_base::xdigit);
132
133   for ( ; low < high; ++low, ++m)
134     *m = ctype_base::mask (_Locale_wchar_ctype(_M_ctype, *low, all_bits));
135   return high;
136 }
137
138 const wchar_t*
139 ctype_byname<wchar_t>
140   ::do_scan_is(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
141 { return find_if(low, high, _STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype)); }
142
143 const wchar_t*
144 ctype_byname<wchar_t>
145   ::do_scan_not(ctype_base::mask  m, const wchar_t* low, const wchar_t* high) const
146 { return find_if(low, high, not1(_STLP_PRIV _Ctype_byname_w_is_mask(m, _M_ctype))); }
147
148 wchar_t ctype_byname<wchar_t>::do_toupper(wchar_t c) const
149 { return _Locale_wchar_toupper(_M_ctype, c); }
150
151 const wchar_t*
152 ctype_byname<wchar_t>::do_toupper(wchar_t* low, const wchar_t* high) const {
153   for ( ; low < high; ++low)
154     *low = _Locale_wchar_toupper(_M_ctype, *low);
155   return high;
156 }
157
158 wchar_t ctype_byname<wchar_t>::do_tolower(wchar_t c) const
159 { return _Locale_wchar_tolower(_M_ctype, c); }
160
161 const wchar_t*
162 ctype_byname<wchar_t>::do_tolower(wchar_t* low, const wchar_t* high) const {
163   for ( ; low < high; ++low)
164     *low = _Locale_wchar_tolower(_M_ctype, *low);
165   return high;
166 }
167
168 #endif /* WCHAR_T */
169
170 // collate_byname<char>
171 collate_byname<char>::collate_byname(const char* name, size_t refs, _Locale_name_hint* hint)
172   : collate<char>(refs),
173     _M_collate(_STLP_PRIV __acquire_collate(name, hint)) {
174   if (!_M_collate)
175     locale::_M_throw_runtime_error();
176 }
177
178 collate_byname<char>::~collate_byname()
179 { _STLP_PRIV __release_collate(_M_collate); }
180
181 int collate_byname<char>::do_compare(const char* __low1,
182                                      const char* __high1,
183                                      const char* __low2,
184                                      const char* __high2) const {
185   return _Locale_strcmp(_M_collate,
186                         __low1, __high1 - __low1,
187                         __low2, __high2 - __low2);
188 }
189
190 collate_byname<char>::string_type
191 collate_byname<char>::do_transform(const char* low, const char* high) const {
192   if (low == high)
193     return string_type();
194
195   size_t n = _Locale_strxfrm(_M_collate, NULL, 0, low, high - low);
196
197   // NOT PORTABLE.  What we're doing relies on internal details of the
198   // string implementation.  (Contiguity of string elements and presence
199   // of trailing zero.)
200   string_type buf(n, 0);
201   _Locale_strxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
202   return buf;
203 }
204
205
206 #if !defined (_STLP_NO_WCHAR_T)
207
208 // collate_byname<wchar_t>
209
210 collate_byname<wchar_t>::collate_byname(const char* name, size_t refs, _Locale_name_hint* hint)
211   : collate<wchar_t>(refs),
212     _M_collate(_STLP_PRIV __acquire_collate(name, hint)) {
213   if (!_M_collate)
214     locale::_M_throw_runtime_error();
215 }
216
217 collate_byname<wchar_t>::~collate_byname()
218 { _STLP_PRIV __release_collate(_M_collate); }
219
220 int collate_byname<wchar_t>::do_compare(const wchar_t* low1,
221                                         const wchar_t* high1,
222                                         const wchar_t* low2,
223                                         const wchar_t* high2) const {
224   return _Locale_strwcmp(_M_collate,
225                          low1, high1 - low1,
226                          low2, high2 - low2);
227 }
228
229 collate_byname<wchar_t>::string_type
230 collate_byname<wchar_t>::do_transform(const wchar_t* low,
231                                       const wchar_t* high) const {
232   if (low == high)
233     return string_type();
234
235   size_t n = _Locale_strwxfrm(_M_collate, NULL, 0, low, high - low);
236
237   // NOT PORTABLE.  What we're doing relies on internal details of the
238   // string implementation.  (Contiguity of string elements and presence
239   // of trailing zero.)
240   string_type buf(n, 0);
241   _Locale_strwxfrm(_M_collate, &(*buf.begin()), n + 1, low, high - low);
242   return buf;
243 }
244
245 #endif /*  _STLP_NO_WCHAR_T */
246
247 _STLP_END_NAMESPACE
248
249 #if !defined (_STLP_NO_MBSTATE_T)
250
251 _STLP_BEGIN_NAMESPACE
252
253 //----------------------------------------------------------------------
254 // codecvt_byname<char>
255
256 codecvt_byname<char, char, mbstate_t>
257   ::codecvt_byname(const char* /* name */, size_t refs)
258     : codecvt<char, char, mbstate_t>(refs) {}
259
260 codecvt_byname<char, char, mbstate_t>::~codecvt_byname() {}
261
262
263 #  if !defined (_STLP_NO_WCHAR_T)
264
265 //----------------------------------------------------------------------
266 // codecvt_byname<wchar_t>
267 codecvt_byname<wchar_t, char, mbstate_t>
268   ::codecvt_byname(const char* name, size_t refs, _Locale_name_hint* hint)
269     : codecvt<wchar_t, char, mbstate_t>(refs),
270       _M_ctype(_STLP_PRIV __acquire_ctype(name, hint)) {
271   if (!_M_ctype)
272     locale::_M_throw_runtime_error();
273 }
274
275 codecvt_byname<wchar_t, char, mbstate_t>::~codecvt_byname()
276 { _STLP_PRIV __release_ctype(_M_ctype); }
277
278 codecvt<wchar_t, char, mbstate_t>::result
279 codecvt_byname<wchar_t, char, mbstate_t>
280   ::do_out(state_type&     state,
281            const wchar_t*  from,
282            const wchar_t*  from_end,
283            const wchar_t*& from_next,
284            char*           to,
285            char*           to_limit,
286            char*&          to_next) const {
287   while (from != from_end) {
288     size_t chars_stored = _Locale_wctomb(_M_ctype,
289                                          to, to_limit - to, *from,
290                                          &state);
291     if (chars_stored == (size_t) -1) {
292       from_next = from;
293       to_next   = to;
294       return error;
295     }
296     else if (chars_stored == (size_t) -2) {
297       from_next = from;
298       to_next   = to;
299       return partial;
300     }
301
302     ++from;
303     to += chars_stored;
304   }
305
306   from_next = from;
307   to_next   = to;
308   return ok;
309 }
310
311 codecvt<wchar_t, char, mbstate_t>::result
312 codecvt_byname<wchar_t, char, mbstate_t>
313   ::do_in(state_type&         state,
314           const extern_type*  from,
315           const extern_type*  from_end,
316           const extern_type*& from_next,
317           intern_type*        to,
318           intern_type*        ,
319           intern_type*&       to_next) const {
320   while (from != from_end) {
321     size_t chars_read = _Locale_mbtowc(_M_ctype,
322                                        to, from, from_end - from,
323                                        &state);
324     if (chars_read == (size_t) -1) {
325       from_next = from;
326       to_next   = to;
327       return error;
328     }
329
330     if (chars_read == (size_t) -2) {
331       from_next = from;
332       to_next   = to;
333       return partial;
334     }
335
336     from += chars_read;
337     to++;
338   }
339
340   from_next = from;
341   to_next   = to;
342   return ok;
343 }
344
345 codecvt<wchar_t, char, mbstate_t>::result
346 codecvt_byname<wchar_t, char, mbstate_t>
347   ::do_unshift(state_type&   state,
348                extern_type*  to,
349                extern_type*  to_limit,
350                extern_type*& to_next) const {
351   to_next = to;
352   size_t result = _Locale_unshift(_M_ctype, &state,
353                                   to, to_limit - to, &to_next);
354   if (result == (size_t) -1)
355     return error;
356   else if (result == (size_t) -2)
357     return partial;
358   else
359 #    if defined (__ISCPP__)
360     return /*to_next == to ? noconv :*/ ok;
361 #    else
362     return to_next == to ? noconv : ok;
363 #    endif
364 }
365
366 int
367 codecvt_byname<wchar_t, char, mbstate_t>::do_encoding() const _STLP_NOTHROW {
368   if (_Locale_is_stateless(_M_ctype)) {
369     int max_width = _Locale_mb_cur_max(_M_ctype);
370     int min_width = _Locale_mb_cur_min(_M_ctype);
371     return min_width == max_width ? min_width : 0;
372   }
373   else
374     return -1;
375 }
376
377 bool codecvt_byname<wchar_t, char, mbstate_t>
378   ::do_always_noconv() const _STLP_NOTHROW {
379   return false;
380 }
381
382 int
383 codecvt_byname<wchar_t, char, mbstate_t>::do_length(const state_type&,
384                                                     const  extern_type* from, const  extern_type* end,
385                                                     size_t mx) const
386 { return (int)(min) ((size_t) (end - from), mx); }
387
388 int
389 codecvt_byname<wchar_t, char, mbstate_t>::do_max_length() const _STLP_NOTHROW
390 { return _Locale_mb_cur_max(_M_ctype); }
391 #  endif
392
393 _STLP_END_NAMESPACE
394
395 #endif /* MBSTATE_T */
396
397 _STLP_BEGIN_NAMESPACE
398
399 // numpunct_byname<char>
400 numpunct_byname<char>::numpunct_byname(const char* name, size_t refs, _Locale_name_hint* hint)
401   : numpunct<char>(refs),
402     _M_numeric(_STLP_PRIV __acquire_numeric(name, hint)) {
403   if (!_M_numeric)
404     locale::_M_throw_runtime_error();
405
406   _M_truename  = _Locale_true(_M_numeric);
407   _M_falsename = _Locale_false(_M_numeric);
408 }
409
410 numpunct_byname<char>::~numpunct_byname()
411 { _STLP_PRIV __release_numeric(_M_numeric); }
412
413 char numpunct_byname<char>::do_decimal_point() const
414 { return _Locale_decimal_point(_M_numeric); }
415
416 char numpunct_byname<char>::do_thousands_sep() const
417 { return _Locale_thousands_sep(_M_numeric); }
418
419 string numpunct_byname<char>::do_grouping() const {
420   const char * __grouping = _Locale_grouping(_M_numeric);
421   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
422     __grouping = "";
423   return __grouping;
424 }
425
426 //----------------------------------------------------------------------
427 // numpunct<wchar_t>
428
429 #if !defined (_STLP_NO_WCHAR_T)
430
431 // numpunct_byname<wchar_t>
432
433 numpunct_byname<wchar_t>::numpunct_byname(const char* name, size_t refs, _Locale_name_hint* hint)
434   : numpunct<wchar_t>(refs),
435     _M_numeric(_STLP_PRIV __acquire_numeric(name, hint)) {
436   if (!_M_numeric)
437     locale::_M_throw_runtime_error();
438
439   const char* truename  = _Locale_true(_M_numeric);
440   const char* falsename = _Locale_false(_M_numeric);
441   _M_truename.resize(strlen(truename));
442   _M_falsename.resize(strlen(falsename));
443   copy(truename,  truename  + strlen(truename), _M_truename.begin());
444   copy(falsename, falsename + strlen(falsename), _M_falsename.begin());
445 }
446
447 numpunct_byname<wchar_t>::~numpunct_byname()
448 { _STLP_PRIV __release_numeric(_M_numeric); }
449
450 wchar_t numpunct_byname<wchar_t>::do_decimal_point() const
451 { return (wchar_t) _Locale_decimal_point(_M_numeric); }
452
453 wchar_t numpunct_byname<wchar_t>::do_thousands_sep() const
454 { return (wchar_t) _Locale_thousands_sep(_M_numeric); }
455
456 string numpunct_byname<wchar_t>::do_grouping() const {
457   const char * __grouping = _Locale_grouping(_M_numeric);
458   if (__grouping != NULL && __grouping[0] == CHAR_MAX)
459     __grouping = "";
460   return __grouping;
461 }
462
463 #endif
464
465 _STLP_MOVE_TO_PRIV_NAMESPACE
466
467 static void _Init_monetary_formats(money_base::pattern& pos_format,
468                                    money_base::pattern& neg_format,
469                                    _Locale_monetary * monetary) {
470   switch (_Locale_p_sign_posn(monetary)) {
471     case 0: // Parentheses surround the quantity and currency_symbol
472     case 1: // The sign string precedes the quantity and currency_symbol
473       pos_format.field[0] = (char) money_base::sign;
474       if (_Locale_p_cs_precedes(monetary)) {
475         // 1 if currency_symbol precedes a positive value
476         pos_format.field[1] = (char) money_base::symbol;
477         if (_Locale_p_sep_by_space(monetary)) {
478           // a space separates currency_symbol from a positive value.
479           pos_format.field[2] = (char) money_base::space;
480           pos_format.field[3] = (char) money_base::value;
481         } else {
482           // a space not separates currency_symbol from a positive value.
483           pos_format.field[2] = (char) money_base::value;
484           pos_format.field[3] = (char) money_base::none;
485         }
486       } else {
487         // 0 if currency_symbol succeeds a positive value
488         pos_format.field[1] = (char) money_base::value;
489         if (_Locale_p_sep_by_space(monetary)) {
490           // a space separates currency_symbol from a positive value.
491           pos_format.field[2] = (char) money_base::space;
492           pos_format.field[3] = (char) money_base::symbol;
493         } else {
494           // a space not separates currency_symbol from a positive value.
495           pos_format.field[2] = (char) money_base::symbol;
496           pos_format.field[3] = (char) money_base::none;
497         }
498       }
499       break;
500     case 2: // The sign string succeeds the quantity and currency_symbol.
501       if (_Locale_p_cs_precedes(monetary)) {
502         // 1 if currency_symbol precedes a positive value
503         pos_format.field[0] = (char) money_base::symbol;
504         if (_Locale_p_sep_by_space(monetary)) {
505           // a space separates currency_symbol from a positive value.
506           pos_format.field[1] = (char) money_base::space;
507           pos_format.field[2] = (char) money_base::value;
508           pos_format.field[3] = (char) money_base::sign;
509         } else {
510           // a space not separates currency_symbol from a positive value.
511           pos_format.field[1] = (char) money_base::value;
512           pos_format.field[2] = (char) money_base::sign;
513           pos_format.field[3] = (char) money_base::none;
514         }
515       } else {
516         // 0 if currency_symbol succeeds a positive value
517         pos_format.field[0] = (char) money_base::value;
518         if (_Locale_p_sep_by_space(monetary)) {
519           // a space separates currency_symbol from a positive value.
520           pos_format.field[1] = (char) money_base::space;
521           pos_format.field[2] = (char) money_base::symbol;
522           pos_format.field[3] = (char) money_base::sign;
523         } else {
524           // a space not separates currency_symbol from a positive value.
525           pos_format.field[1] = (char) money_base::symbol;
526           pos_format.field[2] = (char) money_base::sign;
527           pos_format.field[3] = (char) money_base::none;
528         }
529       }
530       break;
531     case 3: // The sign string immediately precedes the currency_symbol.
532       if (_Locale_p_cs_precedes(monetary)) {
533         // 1 if currency_symbol precedes a positive value
534         pos_format.field[0] = (char) money_base::sign;
535         pos_format.field[1] = (char) money_base::symbol;
536         if (_Locale_p_sep_by_space(monetary)) {
537           // a space separates currency_symbol from a positive value.
538           pos_format.field[2] = (char) money_base::space;
539           pos_format.field[3] = (char) money_base::value;
540         } else {
541           // a space not separates currency_symbol from a positive value.
542           pos_format.field[2] = (char) money_base::value;
543           pos_format.field[3] = (char) money_base::none;
544         }
545       } else {
546         // 0 if currency_symbol succeeds a positive value
547         pos_format.field[0] = (char) money_base::value;
548         pos_format.field[1] = (char) money_base::sign;
549         pos_format.field[2] = (char) money_base::symbol;
550         pos_format.field[3] = (char) money_base::none;
551       }
552       break;
553     case 4: // The sign string immediately succeeds the currency_symbol.
554     default:
555       if (_Locale_p_cs_precedes(monetary)) {
556         // 1 if currency_symbol precedes a positive value
557         pos_format.field[0] = (char) money_base::symbol;
558         pos_format.field[1] = (char) money_base::sign;
559         pos_format.field[2] = (char) money_base::value;
560         pos_format.field[3] = (char) money_base::none;
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   }
578
579   switch (_Locale_n_sign_posn(monetary)) {
580     case 0: // Parentheses surround the quantity and currency_symbol
581     case 1: // The sign string precedes the quantity and currency_symbol
582       neg_format.field[0] = (char) money_base::sign;
583       if (_Locale_n_cs_precedes(monetary)) {
584         // 1 if currency_symbol precedes a negative value
585         neg_format.field[1] = (char) money_base::symbol;
586         if (_Locale_n_sep_by_space(monetary)) {
587           // a space separates currency_symbol from a negative value.
588           neg_format.field[2] = (char) money_base::space;
589           neg_format.field[3] = (char) money_base::value;
590         } else {
591           // a space not separates currency_symbol from a negative value.
592           neg_format.field[2] = (char) money_base::value;
593           neg_format.field[3] = (char) money_base::none;
594         }
595       } else {
596         // 0 if currency_symbol succeeds a negative value
597         neg_format.field[1] = (char) money_base::value;
598         if (_Locale_n_sep_by_space(monetary)) {
599           // a space separates currency_symbol from a negative value.
600           neg_format.field[2] = (char) money_base::space;
601           neg_format.field[3] = (char) money_base::symbol;
602         } else {
603           // a space not separates currency_symbol from a negative value.
604           neg_format.field[2] = (char) money_base::symbol;
605           neg_format.field[3] = (char) money_base::none;
606         }
607       }
608       break;
609     case 2: // The sign string succeeds the quantity and currency_symbol.
610       if (_Locale_n_cs_precedes(monetary)) {
611         // 1 if currency_symbol precedes a negative value
612         neg_format.field[0] = (char) money_base::symbol;
613         if (_Locale_n_sep_by_space(monetary)) {
614           // a space separates currency_symbol from a negative value.
615           neg_format.field[1] = (char) money_base::space;
616           neg_format.field[2] = (char) money_base::value;
617           neg_format.field[3] = (char) money_base::sign;
618         } else {
619           // a space not separates currency_symbol from a negative value.
620           neg_format.field[1] = (char) money_base::value;
621           neg_format.field[2] = (char) money_base::sign;
622           neg_format.field[3] = (char) money_base::none;
623         }
624       } else {
625         // 0 if currency_symbol succeeds a negative value
626         neg_format.field[0] = (char) money_base::value;
627         if (_Locale_n_sep_by_space(monetary)) {
628           // a space separates currency_symbol from a negative value.
629           neg_format.field[1] = (char) money_base::space;
630           neg_format.field[2] = (char) money_base::symbol;
631           neg_format.field[3] = (char) money_base::sign;
632         } else {
633           // a space not separates currency_symbol from a negative value.
634           neg_format.field[1] = (char) money_base::symbol;
635           neg_format.field[2] = (char) money_base::sign;
636           neg_format.field[3] = (char) money_base::none;
637         }
638       }
639       break;
640     case 3: // The sign string immediately precedes the currency_symbol.
641       if (_Locale_n_cs_precedes(monetary)) {
642         // 1 if currency_symbol precedes a negative value
643         neg_format.field[0] = (char) money_base::sign;
644         neg_format.field[1] = (char) money_base::symbol;
645         if (_Locale_n_sep_by_space(monetary)) {
646           // a space separates currency_symbol from a negative value.
647           neg_format.field[2] = (char) money_base::space;
648           neg_format.field[3] = (char) money_base::value;
649         } else {
650           // a space not separates currency_symbol from a negative value.
651           neg_format.field[2] = (char) money_base::value;
652           neg_format.field[3] = (char) money_base::none;
653         }
654       } else {
655         // 0 if currency_symbol succeeds a negative value
656         neg_format.field[0] = (char) money_base::value;
657         neg_format.field[1] = (char) money_base::sign;
658         neg_format.field[2] = (char) money_base::symbol;
659         neg_format.field[3] = (char) money_base::none;
660       }
661       break;
662     case 4: // The sign string immediately succeeds the currency_symbol.
663     default:
664       if (_Locale_n_cs_precedes(monetary)) {
665         // 1 if currency_symbol precedes a negative value
666         neg_format.field[0] = (char) money_base::symbol;
667         neg_format.field[1] = (char) money_base::sign;
668         neg_format.field[2] = (char) money_base::value;
669         neg_format.field[3] = (char) money_base::none;
670       } else {
671         // 0 if currency_symbol succeeds a negative value
672         neg_format.field[0] = (char) money_base::value;
673         if (_Locale_n_sep_by_space(monetary)) {
674           // a space separates currency_symbol from a negative value.
675           neg_format.field[1] = (char) money_base::space;
676           neg_format.field[2] = (char) money_base::symbol;
677           neg_format.field[3] = (char) money_base::sign;
678         } else {
679           // a space not separates currency_symbol from a negative value.
680           neg_format.field[1] = (char) money_base::symbol;
681           neg_format.field[2] = (char) money_base::sign;
682           neg_format.field[3] = (char) money_base::none;
683         }
684       }
685       break;
686   }
687 }
688
689 // international variant of monetary
690
691 /*
692  * int_curr_symbol
693  *
694  *   The international currency symbol. The operand is a four-character
695  *   string, with the first three characters containing the alphabetic
696  *   international currency symbol in accordance with those specified
697  *   in the ISO 4217 specification. The fourth character is the character used
698  *   to separate the international currency symbol from the monetary quantity.
699  *
700  * (http://www.opengroup.org/onlinepubs/7990989775/xbd/locale.html)
701  */
702
703 /*
704  * Standards are unclear in the usage of international currency
705  * and monetary formats.
706  * But I am expect that international currency symbol should be the first
707  * (not depends upon where currency symbol situated in the national
708  * format).
709  *
710  * If this isn't so, let's see:
711  *       1 234.56 RUR
712  *       GBP 1,234.56
713  *       USD 1,234.56
714  * The situation really is worse than you see above:
715  * RUR typed wrong here---it prints '1 234.56 RUR ' (see space after RUR).
716  * This is due to intl_fmp.curr_symbol() == "RUR ". (see reference in comments
717  * above).
718  *
719  */
720
721 static void _Init_monetary_formats_int(money_base::pattern& pos_format,
722                                        money_base::pattern& neg_format,
723                                        _Locale_monetary * monetary)
724 {
725   pos_format.field[0] = (char) money_base::symbol;
726   // pos_format.field[1] = (char) money_base::space;
727
728   switch (_Locale_p_sign_posn(monetary)) {
729     case 0: // Parentheses surround the quantity and currency_symbol
730     case 1: // The sign string precedes the quantity and currency_symbol
731       pos_format.field[1] = (char) money_base::sign;
732       pos_format.field[2] = (char) money_base::value;
733       break;
734     case 2: // The sign string succeeds the quantity and currency_symbol.
735       pos_format.field[1] = (char) money_base::value;
736       pos_format.field[2] = (char) money_base::sign;
737       break;
738     case 3: // The sign string immediately precedes the currency_symbol.
739     case 4: // The sign string immediately succeeds the currency_symbol.
740     default:
741       if (_Locale_p_cs_precedes(monetary)) {
742         // 1 if currency_symbol precedes a positive value
743         pos_format.field[1] = (char) money_base::sign;
744         pos_format.field[2] = (char) money_base::value;
745       } else {
746         // 0 if currency_symbol succeeds a positive value
747         pos_format.field[1] = (char) money_base::value;
748         pos_format.field[2] = (char) money_base::sign;
749       }
750       break;
751   }
752   pos_format.field[3] = (char) money_base::none;
753
754   neg_format.field[0] = (char) money_base::symbol;
755   // neg_format.field[1] = (char) money_base::space;
756
757   switch (_Locale_n_sign_posn(monetary)) {
758     case 0: // Parentheses surround the quantity and currency_symbol
759     case 1: // The sign string precedes the quantity and currency_symbol
760       neg_format.field[1] = (char) money_base::sign;
761       neg_format.field[2] = (char) money_base::value;
762       break;
763     case 2: // The sign string succeeds the quantity and currency_symbol.
764       neg_format.field[1] = (char) money_base::value;
765       neg_format.field[2] = (char) money_base::sign;
766       break;
767     case 3: // The sign string immediately precedes the currency_symbol.
768     case 4: // The sign string immediately succeeds the currency_symbol.
769     default:
770       if (_Locale_n_cs_precedes(monetary)) {
771         // 1 if currency_symbol precedes a negative value
772         neg_format.field[1] = (char) money_base::sign;
773         neg_format.field[2] = (char) money_base::value;
774       } else {
775         // 0 if currency_symbol succeeds a negative value
776         neg_format.field[1] = (char) money_base::value;
777         neg_format.field[2] = (char) money_base::sign;
778       }
779       break;
780   }
781   neg_format.field[3] = (char) money_base::none;
782 }
783
784 _STLP_MOVE_TO_STD_NAMESPACE
785
786 //
787 // moneypunct_byname<>
788 //
789 moneypunct_byname<char, true>::moneypunct_byname(const char * name,
790                                                  size_t refs, _Locale_name_hint* hint):
791   moneypunct<char, true>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
792   if (!_M_monetary)
793     locale::_M_throw_runtime_error();
794   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
795 }
796
797 moneypunct_byname<char, true>::~moneypunct_byname()
798 { _STLP_PRIV __release_monetary(_M_monetary); }
799
800 char moneypunct_byname<char, true>::do_decimal_point() const
801 { return _Locale_mon_decimal_point(_M_monetary); }
802
803 char moneypunct_byname<char, true>::do_thousands_sep() const
804 { return _Locale_mon_thousands_sep(_M_monetary); }
805
806 string moneypunct_byname<char, true>::do_grouping() const
807 { return _Locale_mon_grouping(_M_monetary); }
808
809 string moneypunct_byname<char, true>::do_curr_symbol() const
810 { return _Locale_int_curr_symbol(_M_monetary); }
811
812 string moneypunct_byname<char, true>::do_positive_sign() const
813 { return _Locale_positive_sign(_M_monetary); }
814
815 string moneypunct_byname<char, true>::do_negative_sign() const
816 { return _Locale_negative_sign(_M_monetary); }
817
818 int moneypunct_byname<char, true>::do_frac_digits() const
819 { return _Locale_int_frac_digits(_M_monetary); }
820
821 moneypunct_byname<char, false>::moneypunct_byname(const char * name,
822                                                   size_t refs, _Locale_name_hint* hint):
823   moneypunct<char, false>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
824   if (!_M_monetary)
825     locale::_M_throw_runtime_error();
826   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
827 }
828
829 moneypunct_byname<char, false>::~moneypunct_byname()
830 { _STLP_PRIV __release_monetary(_M_monetary); }
831
832 char moneypunct_byname<char, false>::do_decimal_point() const
833 { return _Locale_mon_decimal_point(_M_monetary); }
834
835 char moneypunct_byname<char, false>::do_thousands_sep() const
836 { return _Locale_mon_thousands_sep(_M_monetary); }
837
838 string moneypunct_byname<char, false>::do_grouping() const
839 { return _Locale_mon_grouping(_M_monetary); }
840
841 string moneypunct_byname<char, false>::do_curr_symbol() const
842 { return _Locale_currency_symbol(_M_monetary); }
843
844 string moneypunct_byname<char, false>::do_positive_sign() const
845 { return _Locale_positive_sign(_M_monetary); }
846
847 string moneypunct_byname<char, false>::do_negative_sign() const
848 { return _Locale_negative_sign(_M_monetary); }
849
850 int moneypunct_byname<char, false>::do_frac_digits() const
851 { return _Locale_frac_digits(_M_monetary); }
852
853 //
854 // moneypunct_byname<wchar_t>
855 //
856 #if !defined (_STLP_NO_WCHAR_T)
857
858 moneypunct_byname<wchar_t, true>::moneypunct_byname(const char * name,
859                                                     size_t refs, _Locale_name_hint* hint):
860   moneypunct<wchar_t, true>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
861   if (!_M_monetary)
862     locale::_M_throw_runtime_error();
863   _STLP_PRIV _Init_monetary_formats_int(_M_pos_format, _M_neg_format, _M_monetary);
864 }
865
866 moneypunct_byname<wchar_t, true>::~moneypunct_byname()
867 { _STLP_PRIV __release_monetary(_M_monetary); }
868
869 wchar_t moneypunct_byname<wchar_t, true>::do_decimal_point() const
870 { return _Locale_mon_decimal_point(_M_monetary); }
871
872 wchar_t moneypunct_byname<wchar_t, true>::do_thousands_sep() const
873 { return _Locale_mon_thousands_sep(_M_monetary); }
874
875 string moneypunct_byname<wchar_t, true>::do_grouping() const
876 { return _Locale_mon_grouping(_M_monetary); }
877
878 inline wstring __do_widen (string const& str) {
879 #if defined (_STLP_NO_MEMBER_TEMPLATES) || defined (_STLP_MSVC) || defined(__MRC__) || defined(__SC__) //*ty 05/26/2001 - added workaround for mpw
880   wstring::_Reserve_t __Reserve;
881   size_t __size = str.size();
882   wstring result(__Reserve, __size);
883   copy(str.begin(), str.end(), result.begin());
884 #else
885   wstring result(str.begin(), str.end());
886 #endif
887   return result;
888 }
889
890 wstring moneypunct_byname<wchar_t, true>::do_curr_symbol() const
891 { return __do_widen(_Locale_int_curr_symbol(_M_monetary)); }
892
893 wstring moneypunct_byname<wchar_t, true>::do_positive_sign() const
894 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
895
896 wstring moneypunct_byname<wchar_t, true>::do_negative_sign() const
897 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
898
899 int moneypunct_byname<wchar_t, true>::do_frac_digits() const
900 { return _Locale_int_frac_digits(_M_monetary); }
901
902 moneypunct_byname<wchar_t, false>::moneypunct_byname(const char * name,
903                                                      size_t refs, _Locale_name_hint* hint):
904   moneypunct<wchar_t, false>(refs), _M_monetary(_STLP_PRIV __acquire_monetary(name, hint)) {
905   if (!_M_monetary)
906     locale::_M_throw_runtime_error() ;
907   _STLP_PRIV _Init_monetary_formats(_M_pos_format, _M_neg_format, _M_monetary);
908 }
909
910 moneypunct_byname<wchar_t, false>::~moneypunct_byname()
911 { _STLP_PRIV __release_monetary(_M_monetary); }
912
913 wchar_t moneypunct_byname<wchar_t, false>::do_decimal_point() const
914 { return _Locale_mon_decimal_point(_M_monetary); }
915
916 wchar_t moneypunct_byname<wchar_t, false>::do_thousands_sep() const
917 { return _Locale_mon_thousands_sep(_M_monetary); }
918
919 string moneypunct_byname<wchar_t, false>::do_grouping() const
920 { return _Locale_mon_grouping(_M_monetary); }
921
922 wstring moneypunct_byname<wchar_t, false>::do_curr_symbol() const
923 { return __do_widen(_Locale_currency_symbol(_M_monetary)); }
924
925 wstring moneypunct_byname<wchar_t, false>::do_positive_sign() const
926 { return __do_widen(_Locale_positive_sign(_M_monetary)); }
927
928 wstring moneypunct_byname<wchar_t, false>::do_negative_sign() const
929 { return __do_widen(_Locale_negative_sign(_M_monetary)); }
930
931 int moneypunct_byname<wchar_t, false>::do_frac_digits() const
932 { return _Locale_frac_digits(_M_monetary); }
933
934 #endif
935
936 _STLP_END_NAMESPACE
937
938 #include "message_facets.h"
939
940 _STLP_BEGIN_NAMESPACE
941
942 _STLP_MOVE_TO_PRIV_NAMESPACE
943
944 void _Catalog_locale_map::insert(nl_catd_type key, const locale& L) {
945   _STLP_TRY {
946 #if !defined(_STLP_NO_TYPEINFO) && !defined(_STLP_NO_RTTI)
947     // Don't bother to do anything unless we're using a non-default ctype facet
948 # ifdef _STLP_NO_WCHAR_T
949     typedef char _Char;
950 # else
951     typedef wchar_t _Char;
952 # endif
953
954     typedef ctype<_Char> wctype;
955     wctype const& wct = use_facet<wctype>(L);
956     if (typeid(wct) != typeid(wctype)) {
957 # endif /* _STLP_NO_TYPEINFO */
958       if (!M)
959         M = new map_type;
960
961 #if defined (__SC__)
962       if (!M) delete M;
963 #endif
964       M->insert(map_type::value_type(key, L));
965 #if !defined(_STLP_NO_TYPEINFO) && !defined(_STLP_NO_RTTI)
966     }
967 # endif /* _STLP_NO_TYPEINFO */
968   }
969   _STLP_CATCH_ALL {}
970 }
971
972 void _Catalog_locale_map::erase(nl_catd_type key) {
973   if (M)
974     M->erase(key);
975 }
976
977 locale _Catalog_locale_map::lookup(nl_catd_type key) const {
978   if (M) {
979     map_type::const_iterator i = M->find(key);
980     return i != M->end() ? (*i).second : locale::classic();
981   }
982   else
983     return locale::classic();
984 }
985
986
987 #if defined (_STLP_USE_NL_CATD_MAPPING)
988 _STLP_VOLATILE __stl_atomic_t _Catalog_nl_catd_map::_count = 0;
989
990 messages_base::catalog _Catalog_nl_catd_map::insert(nl_catd_type cat) {
991   messages_base::catalog &res = Mr[cat];
992   if ( res == 0 ) {
993 #if defined (_STLP_ATOMIC_INCREMENT)
994     res = __STATIC_CAST(int, _STLP_ATOMIC_INCREMENT(&_count));
995 #else
996     static _STLP_STATIC_MUTEX _Count_lock _STLP_MUTEX_INITIALIZER;
997     {
998       _STLP_auto_lock sentry(_Count_lock);
999       res = __STATIC_CAST(int, ++_count);
1000     }
1001 #endif
1002     M[res] = cat;
1003   }
1004   return res;
1005 }
1006
1007 void _Catalog_nl_catd_map::erase(messages_base::catalog cat) {
1008   map_type::iterator mit(M.find(cat));
1009   if (mit != M.end()) {
1010     Mr.erase((*mit).second);
1011     M.erase(mit);
1012   }
1013 }
1014 #endif
1015
1016 //----------------------------------------------------------------------
1017 //
1018 //
1019
1020 _Messages_impl::_Messages_impl(bool is_wide, _Locale_name_hint* hint) :
1021   _M_message_obj(0), _M_map(0) {
1022   _M_delete = true;
1023   if (is_wide)
1024     _M_map = new _Catalog_locale_map;
1025   _M_message_obj = __acquire_messages("C", hint);
1026 }
1027
1028 _Messages_impl::_Messages_impl(bool is_wide, _Locale_messages* msg_obj ) :
1029   _M_message_obj(msg_obj), _M_map(0) {
1030   _M_delete = true;
1031   if (is_wide)
1032     _M_map = new _Catalog_locale_map;
1033 }
1034
1035 _Messages_impl::~_Messages_impl() {
1036   __release_messages(_M_message_obj);
1037   if (_M_map) delete _M_map;
1038 }
1039
1040 _Messages::catalog _Messages_impl::do_open(const string& filename, const locale& L) const {
1041   nl_catd_type result = _M_message_obj ? _Locale_catopen(_M_message_obj, filename.c_str())
1042     : (nl_catd_type)(-1);
1043
1044   if ( result != (nl_catd_type)(-1) ) {
1045     if ( _M_map != 0 ) {
1046       _M_map->insert(result, L);
1047     }
1048     return _M_cat.insert( result );
1049   }
1050
1051   return -1;
1052 }
1053
1054 string _Messages_impl::do_get(catalog cat,
1055                               int set, int p_id, const string& dfault) const {
1056   return _M_message_obj != 0 && cat >= 0
1057     ? string(_Locale_catgets(_M_message_obj, _M_cat[cat], set, p_id, dfault.c_str()))
1058     : dfault;
1059 }
1060
1061 #if !defined (_STLP_NO_WCHAR_T)
1062
1063 wstring
1064 _Messages_impl::do_get(catalog thecat,
1065                        int set, int p_id, const wstring& dfault) const {
1066   typedef ctype<wchar_t> wctype;
1067   const wctype& ct = use_facet<wctype>(_M_map->lookup( _M_cat[thecat] ) );
1068
1069   const char* str = _Locale_catgets(_M_message_obj, _M_cat[thecat], set, p_id, "");
1070
1071   // Verify that the lookup failed; an empty string might represent success.
1072   if (!str)
1073     return dfault;
1074   else if (str[0] == '\0') {
1075     const char* str2 = _Locale_catgets(_M_message_obj, _M_cat[thecat], set, p_id, "*");
1076     if (!str2 || ((str2[0] == '*') && (str2[1] == '\0')))
1077       return dfault;
1078   }
1079
1080   // str is correct.  Now we must widen it to get a wstring.
1081   size_t n = strlen(str);
1082
1083   // NOT PORTABLE.  What we're doing relies on internal details of the
1084   // string implementation.  (Contiguity of string elements.)
1085   wstring result(n, wchar_t(0));
1086   ct.widen(str, str + n, &*result.begin());
1087   return result;
1088 }
1089
1090 #endif
1091
1092 void _Messages_impl::do_close(catalog thecat) const {
1093   if (_M_message_obj)
1094     _Locale_catclose(_M_message_obj, _M_cat[thecat]);
1095   if (_M_map) _M_map->erase(_M_cat[thecat]);
1096   _M_cat.erase( thecat );
1097 }
1098
1099 _STLP_MOVE_TO_STD_NAMESPACE
1100
1101 //----------------------------------------------------------------------
1102 // messages<char>
1103
1104 messages<char>::messages(size_t refs) :
1105   locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(false)) {}
1106
1107 messages<char>::messages(size_t refs, _Locale_messages* msg_obj) : locale::facet(refs),
1108   _M_impl(new _STLP_PRIV _Messages_impl(false, msg_obj)) {}
1109
1110
1111 //----------------------------------------------------------------------
1112 // messages_byname<char>
1113
1114 messages_byname<char>::messages_byname(const char* name, size_t refs, _Locale_name_hint* hint)
1115   : messages<char>(refs, name ? _STLP_PRIV __acquire_messages(name, hint) : 0) {}
1116
1117 messages_byname<char>::~messages_byname() {}
1118
1119 #if !defined (_STLP_NO_WCHAR_T)
1120
1121 //----------------------------------------------------------------------
1122 // messages<wchar_t>
1123
1124 messages<wchar_t>::messages(size_t refs)  :
1125   locale::facet(refs), _M_impl(new _STLP_PRIV _Messages_impl(true)) {}
1126
1127 messages<wchar_t>::messages(size_t refs, _Locale_messages* msg_obj)
1128   : locale::facet(refs),
1129     _M_impl(new _STLP_PRIV _Messages_impl(true, msg_obj)) {}
1130
1131 //----------------------------------------------------------------------
1132 // messages_byname<wchar_t>
1133
1134
1135 messages_byname<wchar_t>::messages_byname(const char* name, size_t refs, _Locale_name_hint* hint)
1136   : messages<wchar_t>(refs, name ? _STLP_PRIV __acquire_messages(name, hint) : 0) {}
1137
1138 messages_byname<wchar_t>::~messages_byname() {}
1139
1140 #endif
1141
1142 _STLP_END_NAMESPACE
1143