]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/stl/stl/_monetary.c
Add STLport 5.1.4
[polintos/scott/priv.git] / include / c++ / stl / stl / _monetary.c
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 #ifndef _STLP_MONETARY_C
19 #define _STLP_MONETARY_C
20
21 # ifndef _STLP_INTERNAL_MONETARY_H
22 #  include <stl/_monetary.h>
23 # endif
24
25 #ifndef _STLP_INTERNAL_IOS_H
26 # include <stl/_ios.h>
27 #endif
28
29 #ifndef _STLP_INTERNAL_NUM_PUT_H
30 # include <stl/_num_put.h>
31 #endif
32
33 #ifndef _STLP_INTERNAL_NUM_GET_H
34 # include <stl/_num_get.h>
35 #endif
36
37 _STLP_BEGIN_NAMESPACE
38
39 #if (_STLP_STATIC_TEMPLATE_DATA > 0)
40
41 #  if !defined (__BORLANDC__)
42 template <class _CharT, class _InputIterator>
43 locale::id money_get<_CharT, _InputIterator>::id;
44
45 template <class _CharT, class _OutputIterator>
46 locale::id money_put<_CharT, _OutputIterator>::id;
47 #  endif
48
49 #  if (defined (__CYGWIN__) || defined (__MINGW32__)) && \
50        defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT)
51 /*
52  * Under cygwin, when STLport is used as a shared library, the id needs
53  * to be specified as imported otherwise they will be duplicated in the
54  * calling executable.
55  */
56 template <>
57 _STLP_DECLSPEC locale::id money_get<char, istreambuf_iterator<char, char_traits<char> > >::id;
58 /*
59 template <>
60 _STLP_DECLSPEC locale::id money_get<char, const char*>::id;
61 */
62
63 template <>
64 _STLP_DECLSPEC locale::id money_put<char, ostreambuf_iterator<char, char_traits<char> > >::id;
65 template <>
66 _STLP_DECLSPEC locale::id money_put<char, char*>::id;
67
68 #    if !defined (_STLP_NO_WCHAR_T)
69 template <>
70 _STLP_DECLSPEC locale::id money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
71 template <>
72 _STLP_DECLSPEC locale::id money_get<wchar_t, const wchar_t*>::id;
73
74 template <>
75 _STLP_DECLSPEC locale::id money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >::id;
76 template <>
77 _STLP_DECLSPEC locale::id money_put<wchar_t, wchar_t*>::id;
78 #    endif
79
80 #  endif
81
82 #else /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
83
84 //typedef money_get<char, const char*> money_get_char;
85 //typedef money_put<char, char*> money_put_char;
86 typedef money_get<char, istreambuf_iterator<char, char_traits<char> > > money_get_char_2;
87 typedef money_put<char, ostreambuf_iterator<char, char_traits<char> > > money_put_char_2;
88
89 //__DECLARE_INSTANCE(locale::id, money_get_char::id, );
90 //__DECLARE_INSTANCE(locale::id, money_put_char::id, );
91 __DECLARE_INSTANCE(locale::id, money_get_char_2::id, );
92 __DECLARE_INSTANCE(locale::id, money_put_char_2::id, );
93
94 #  ifndef _STLP_NO_WCHAR_T
95
96 //typedef money_get<wchar_t, const wchar_t*> money_get_wchar_t;
97 //typedef money_get<wchar_t, istreambuf_iterator<wchar_t, char_traits<wchar_t> > > money_get_wchar_t_2;
98 typedef money_put<wchar_t, wchar_t*> money_put_wchar_t;
99 typedef money_put<wchar_t, ostreambuf_iterator<wchar_t, char_traits<wchar_t> > > money_put_wchar_t_2;
100
101 //__DECLARE_INSTANCE(locale::id, money_get_wchar_t::id, );
102 //__DECLARE_INSTANCE(locale::id, money_put_wchar_t::id, );
103 __DECLARE_INSTANCE(locale::id, money_get_wchar_t_2::id, );
104 __DECLARE_INSTANCE(locale::id, money_put_wchar_t_2::id, );
105
106 #  endif
107 #endif /* ( _STLP_STATIC_TEMPLATE_DATA > 0 ) */
108
109 // money_get facets
110
111 _STLP_MOVE_TO_PRIV_NAMESPACE
112
113 // helper functions for do_get
114 template <class _InIt1, class _InIt2>
115 pair<_InIt1, bool> __get_string( _InIt1 __first, _InIt1 __last,
116                                  _InIt2 __str_first, _InIt2 __str_last) {
117   while ( __first != __last && __str_first != __str_last && *__first == *__str_first ) {
118     ++__first;
119     ++__str_first;
120   }
121   return make_pair(__first, __str_first == __str_last);
122 }
123
124 template <class _InIt, class _OuIt, class _CharT>
125 bool
126 __get_monetary_value(_InIt& __first, _InIt __last, _OuIt __out_ite,
127                      const ctype<_CharT>& _c_type,
128                      _CharT __point, int __frac_digits, _CharT __sep,
129                      const string& __grouping, bool &__syntax_ok) {
130   if (__first == __last || !_c_type.is(ctype_base::digit, *__first))
131     return false;
132
133   char __group_sizes[128];
134   char* __group_sizes_end = __grouping.empty()? 0 : __group_sizes;
135   char   __current_group_size = 0;
136
137   while (__first != __last) {
138     if (_c_type.is(ctype_base::digit, *__first)) {
139       ++__current_group_size;
140       *__out_ite++ = *__first++;
141     }
142     else if (__group_sizes_end) {
143       if (*__first == __sep) {
144         *__group_sizes_end++ = __current_group_size;
145         __current_group_size = 0;
146         ++__first;
147       }
148       else break;
149     }
150     else
151       break;
152   }
153
154   if (__grouping.empty())
155     __syntax_ok = true;
156   else {
157     if (__group_sizes_end != __group_sizes)
158       *__group_sizes_end++ = __current_group_size;
159
160     __syntax_ok = __valid_grouping(__group_sizes, __group_sizes_end,
161                                    __grouping.data(), __grouping.data()+ __grouping.size());
162
163     if (__first == __last || *__first != __point) {
164       for (int __digits = 0; __digits != __frac_digits; ++__digits)
165         *__out_ite++ = _CharT('0');
166       return true; // OK not to have decimal point
167     }
168   }
169
170   ++__first;
171
172   int __digits = 0;
173
174   while (__first != __last && _c_type.is(ctype_base::digit, *__first)) {
175       *__out_ite++ = *__first++;
176      ++__digits;
177   }
178
179   __syntax_ok = __syntax_ok && (__digits == __frac_digits);
180
181   return true;
182 }
183
184
185 template <class _CharT, class _InputIter, class _StrType>
186 _InputIter __money_do_get(_InputIter __s, _InputIter __end, bool  __intl,
187                      ios_base&  __str, ios_base::iostate&  __err,
188                      _StrType& __digits, bool &__is_positive, _CharT* /*__dummy*/) {
189   if (__s == __end) {
190     __err |= ios_base::eofbit;
191     return __s;
192   }
193
194   typedef _CharT char_type;
195   typedef _StrType string_type;
196   typedef _InputIter iter_type;
197   typedef moneypunct<char_type, false> _Punct;
198   typedef moneypunct<char_type, true>  _Punct_intl;
199   typedef ctype<char_type>             _Ctype;
200
201   locale __loc = __str.getloc();
202   const _Punct&      __punct      = use_facet<_Punct>(__loc) ;
203   const _Punct_intl& __punct_intl = use_facet<_Punct_intl>(__loc) ;
204   const _Ctype&      __c_type     = use_facet<_Ctype>(__loc) ;
205
206   money_base::pattern __format = __intl ? __punct_intl.neg_format()
207                                         : __punct.neg_format();
208   string_type __ns = __intl ? __punct_intl.negative_sign()
209                             : __punct.negative_sign();
210   string_type __ps = __intl ? __punct_intl.positive_sign()
211                             : __punct.positive_sign();
212   int __i;
213   bool __symbol_required = (__str.flags() & ios_base::showbase) != 0;
214   string_type __buf;
215   back_insert_iterator<string_type> __out_ite(__buf);
216
217   for (__i = 0; __i < 4; ++__i) {
218     switch (__format.field[__i]) {
219     case money_base::none:
220       if (__i == 3) {
221         if (__c_type.is(ctype_base::space, *__s)) {
222           __err = ios_base::failbit;
223           return __s;
224         }
225         break;
226       }
227       while (__s != __end && __c_type.is(ctype_base::space, *__s))
228         ++__s;
229       break;
230     case money_base::space:
231       if (!__c_type.is(ctype_base::space, *__s)) {
232         __err = ios_base::failbit;
233         return __s;
234       }
235       ++__s;
236       while (__s != __end && __c_type.is(ctype_base::space, *__s))
237         ++__s;
238       break;
239     case money_base::symbol: {
240       string_type __curs = __intl ? __punct_intl.curr_symbol()
241                                   : __punct.curr_symbol();
242       pair<iter_type, bool>
243       __result  = __get_string(__s, __end, __curs.begin(), __curs.end());
244       if (!__result.second && __symbol_required)
245         __err = ios_base::failbit;
246       __s = __result.first;
247       break;
248     }
249     case money_base::sign: {
250       if (__s == __end) {
251         if (__ps.empty())
252           break;
253         if (__ns.empty()) {
254           __is_positive = false;
255           break;
256         }
257         __err = ios_base::failbit;
258         return __s;
259       }
260       else {
261         if (__ps.empty()) {
262           if (__ns.empty())
263             break;
264           if (*__s == __ns[0]) {
265             ++__s;
266             __is_positive = false;
267           }
268           break;
269         }
270         else {
271           if (*__s == __ps[0]) {
272             ++__s;
273             break;
274           }
275           if (__ns.empty())
276             break;
277           if (*__s == __ns[0]) {
278             ++__s;
279             __is_positive = false;
280             break;
281           }
282           __err = ios_base::failbit;
283         }
284       }
285       return __s;
286     }
287     case money_base::value: {
288       char_type __point = __intl ? __punct_intl.decimal_point()
289                                  : __punct.decimal_point();
290       int __frac_digits = __intl ? __punct_intl.frac_digits()
291                                  : __punct.frac_digits();
292       string __grouping = __intl ? __punct_intl.grouping()
293                                  : __punct.grouping();
294       bool __syntax_ok = true;
295
296       bool __result;
297
298       char_type __sep = __grouping.empty() ? char_type() :
299       __intl ? __punct_intl.thousands_sep() : __punct.thousands_sep();
300
301       __result = __get_monetary_value(__s, __end, __out_ite, __c_type,
302                                       __point, __frac_digits,
303                                       __sep,
304                                       __grouping, __syntax_ok);
305
306       if (!__syntax_ok)
307         __err |= ios_base::failbit;
308       if (!__result) {
309         __err = ios_base::failbit;
310         return __s;
311       }
312       break;
313
314     }                           // Close money_base::value case
315     }                           // Close switch statement
316   }                             // Close for loop
317
318   if (__is_positive) {
319     if (__ps.size() > 1) {
320       pair<_InputIter, bool>
321         __result = __get_string(__s, __end, __ps.begin() + 1, __ps.end());
322       __s = __result.first;
323       if (!__result.second)
324         __err |= ios::failbit;
325     }
326     if (!(__err & ios_base::failbit))
327       __digits = __buf;
328   }
329   else {
330     if (__ns.size() > 1) {
331       pair<_InputIter, bool>
332         __result = __get_string(__s, __end, __ns.begin() + 1, __ns.end());
333       __s = __result.first;
334       if (!__result.second)
335         __err |= ios::failbit;
336     }
337     if (!(__err & ios::failbit)) {
338       __digits = __c_type.widen('-');
339       __digits += __buf;
340     }
341   }
342   if (__s == __end)
343     __err |= ios::eofbit;
344
345   return __s;
346 }
347
348 _STLP_MOVE_TO_STD_NAMESPACE
349
350 //===== methods ======
351 template <class _CharT, class _InputIter>
352 _InputIter
353 money_get<_CharT, _InputIter>::do_get(_InputIter __s, _InputIter  __end, bool  __intl,
354                                       ios_base&  __str, ios_base::iostate& __err,
355                                       _STLP_LONGEST_FLOAT_TYPE& __units) const {
356   string_type __buf;
357   bool __is_positive = true;
358   __s = _STLP_PRIV __money_do_get(__s, __end, __intl, __str, __err, __buf, __is_positive, (_CharT*)0);
359
360   if (__err == ios_base::goodbit || __err == ios_base::eofbit) {
361     typename string_type::iterator __b = __buf.begin(), __e = __buf.end();
362
363     if (!__is_positive) ++__b;
364     // Can't use atold, since it might be wchar_t. Don't get confused by name below :
365     // it's perfectly capable of reading long double.
366     _STLP_PRIV __get_decimal_integer(__b, __e, __units, (_CharT*)0);
367
368     if (!__is_positive) {
369       __units = -__units;
370     }
371   }
372
373   return __s;
374 }
375
376 template <class _CharT, class _InputIter>
377 _InputIter
378 money_get<_CharT, _InputIter>::do_get(iter_type __s, iter_type  __end, bool  __intl,
379                                       ios_base&  __str, ios_base::iostate&  __err,
380                                       string_type& __digits) const {
381   bool __is_positive = true;
382   return _STLP_PRIV __money_do_get(__s, __end, __intl, __str, __err, __digits, __is_positive, (_CharT*)0);
383 }
384
385 // money_put facets
386
387 _STLP_MOVE_TO_PRIV_NAMESPACE
388
389 template <class _CharT, class _OutputIter, class _Str_Type, class _Str>
390 _OutputIter __money_do_put(_OutputIter __s, bool  __intl, ios_base&  __str,
391                            _CharT __fill, const _Str& __digits, bool __check_digits,
392                            _Str_Type * /*__dummy*/) {
393   typedef _CharT char_type;
394   typedef _Str_Type string_type;
395   typedef ctype<char_type>             _Ctype;
396   typedef moneypunct<char_type, false> _Punct;
397   typedef moneypunct<char_type, true>  _Punct_intl;
398
399   locale __loc = __str.getloc();
400   const _Ctype&      __c_type     = use_facet<_Ctype>(__loc) ;
401   const _Punct&      __punct      = use_facet<_Punct>(__loc) ;
402   const _Punct_intl& __punct_intl = use_facet<_Punct_intl>(__loc) ;
403
404   // some special characters
405   char_type __minus = __c_type.widen('-');
406   char_type __plus  = __c_type.widen('+');
407   char_type __space = __c_type.widen(' ');
408   char_type __zero  = __c_type.widen('0');
409   char_type __point = __intl ? __punct_intl.decimal_point()
410                              : __punct.decimal_point();
411
412   char_type __sep = __intl ? __punct_intl.thousands_sep()
413                            : __punct.thousands_sep();
414
415   string __grouping = __intl ? __punct_intl.grouping()
416                              : __punct.grouping();
417
418   int __frac_digits      = __intl ? __punct_intl.frac_digits()
419                                   : __punct.frac_digits();
420
421   string_type __curr_sym = __intl ? __punct_intl.curr_symbol()
422                                   : __punct.curr_symbol();
423
424   // if there are no digits we are going to return __s.  If there
425   // are digits, but not enough to fill the frac_digits, we are
426   // going to add zeros.  I don't know whether this is right or
427   // not.
428   if (__digits.empty())
429     return __s;
430
431   typename string_type::const_iterator __digits_first = __digits.begin();
432   typename string_type::const_iterator __digits_last  = __digits.end();
433
434   bool __is_negative = *__digits_first == __minus;
435   if (__is_negative)
436     ++__digits_first;
437
438 #if !defined (__BORLANDC__)
439   string_type __sign = __intl ? __is_negative ? __punct_intl.negative_sign()
440                                               : __punct_intl.positive_sign()
441                               : __is_negative ? __punct.negative_sign()
442                                               : __punct.positive_sign();
443 #else
444   string_type __sign;
445   if (__intl) {
446     if (__is_negative)
447       __sign = __punct_intl.negative_sign();
448     else
449       __sign = __punct_intl.positive_sign();
450   }
451   else {
452     if (__is_negative)
453       __sign = __punct.negative_sign();
454     else
455       __sign = __punct.positive_sign();
456   }
457 #endif
458
459   if (__check_digits) {
460     typename string_type::const_iterator __cp = __digits_first;
461     while (__cp != __digits_last && __c_type.is(ctype_base::digit, *__cp))
462       ++__cp;
463     if (__cp == __digits_first)
464       return __s;
465     __digits_last = __cp;
466   }
467
468   // If grouping is required, we make a copy of __digits and
469   // insert the grouping.
470   _STLP_BASIC_IOSTRING(char_type) __new_digits;
471   if (!__grouping.empty()) {
472     __new_digits.assign(__digits_first, __digits_last);
473     __insert_grouping(__new_digits,
474                       __new_digits.size() - __frac_digits,
475                       __grouping,
476                       __sep, __plus, __minus, 0);
477     __digits_first = __new_digits.begin(); // <<--
478     __digits_last  = __new_digits.end();   // <<--
479   }
480
481   // Determine the amount of padding required, if any.
482   streamsize __width = __str.width();
483
484 #if defined (_STLP_DEBUG) && (defined(__HP_aCC) && (__HP_aCC <= 1))
485   size_t __value_length = operator -(__digits_last, __digits_first);
486 #else
487   size_t __value_length = __digits_last - __digits_first;
488 #endif
489
490   size_t __length = __value_length + __sign.size();
491
492   if (__frac_digits != 0)
493     ++__length;
494
495   bool __generate_curr = (__str.flags() & ios_base::showbase) !=0;
496   if (__generate_curr)
497     __length += __curr_sym.size();
498   money_base::pattern __format = __intl ? (__is_negative ? __punct_intl.neg_format()
499                                                          : __punct_intl.pos_format())
500                                         : (__is_negative ? __punct.neg_format()
501                                                          : __punct.pos_format());
502   {
503     //For the moment the following is commented for decoding reason.
504     //No reason to add a space last if the money symbol do not have to be display
505     //if (__format.field[3] == (char) money_base::symbol && !__generate_curr) {
506     //  if (__format.field[2] == (char) money_base::space) {
507     //    __format.field[2] = (char) money_base::none;
508     //  }
509     //}
510     //space can only be second or third and only once (22.2.6.3-1):
511     if ((__format.field[1] == (char) money_base::space) ||
512         (__format.field[2] == (char) money_base::space))
513       ++__length;
514   }
515
516   const bool __need_fill = (((sizeof(streamsize) > sizeof(size_t)) && (__STATIC_CAST(streamsize, __length) < __width)) ||
517                             ((sizeof(streamsize) <= sizeof(size_t)) && (__length < __STATIC_CAST(size_t, __width))));
518   streamsize __fill_amt = __need_fill ? __width - __length : 0;
519
520   ios_base::fmtflags __fill_pos = __str.flags() & ios_base::adjustfield;
521
522   if (__fill_amt != 0 &&
523       !(__fill_pos & (ios_base::left | ios_base::internal)))
524     __s = __fill_n(__s, __fill_amt, __fill);
525
526   for (int __i = 0; __i < 4; ++__i) {
527     char __ffield = __format.field[__i];
528     switch (__ffield) {
529       case money_base::none:
530         if (__fill_amt != 0 && __fill_pos == ios_base::internal)
531           __s = __fill_n(__s, __fill_amt, __fill);
532         break;
533       case money_base::space:
534         *__s++ = __space;
535         if (__fill_amt != 0 && __fill_pos == ios_base::internal)
536           __s = __fill_n(__s, __fill_amt, __fill);
537         break;
538       case money_base::symbol:
539         if (__generate_curr)
540           __s = copy(__curr_sym.begin(), __curr_sym.end(), __s);
541         break;
542       case money_base::sign:
543         if (!__sign.empty())
544           *__s++ = __sign[0];
545         break;
546       case money_base::value:
547         if (__frac_digits == 0) {
548           __s = copy(__digits_first, __digits_last, __s);
549         } else {
550           if ((int)__value_length <= __frac_digits) {
551             // if we see '9' here, we should out 0.09
552             *__s++ = __zero;  // integer part is zero
553             *__s++ = __point; // decimal point
554             __s =  __fill_n(__s, __frac_digits - __value_length, __zero); // zeros
555             __s = copy(__digits_first, __digits_last, __s); // digits
556           } else {
557             __s = copy(__digits_first, __digits_last - __frac_digits, __s);
558             if (__frac_digits != 0) {
559               *__s++ = __point;
560               __s = copy(__digits_last - __frac_digits, __digits_last, __s);
561             }
562           }
563         }
564         break;
565     } //Close for switch
566   } // Close for loop
567
568   // Ouput rest of sign if necessary.
569   if (__sign.size() > 1)
570     __s = copy(__sign.begin() + 1, __sign.end(), __s);
571   if (__fill_amt != 0 &&
572       !(__fill_pos & (ios_base::right | ios_base::internal)))
573     __s = __fill_n(__s, __fill_amt, __fill);
574
575   return __s;
576 }
577
578 _STLP_MOVE_TO_STD_NAMESPACE
579
580 template <class _CharT, class _OutputIter>
581 _OutputIter
582 money_put<_CharT, _OutputIter>
583  ::do_put(_OutputIter __s, bool __intl, ios_base& __str,
584           char_type __fill, _STLP_LONGEST_FLOAT_TYPE __units) const {
585   _STLP_BASIC_IOSTRING(char_type) __digits;
586   _STLP_PRIV __get_money_digits(__digits, __str, __units);
587   return _STLP_PRIV __money_do_put(__s, __intl, __str, __fill, __digits, false, __STATIC_CAST(string_type*, 0));
588 }
589
590 template <class _CharT, class _OutputIter>
591 _OutputIter
592 money_put<_CharT, _OutputIter>
593  ::do_put(_OutputIter __s, bool __intl, ios_base& __str,
594           char_type __fill, const string_type& __digits) const {
595   return _STLP_PRIV __money_do_put(__s, __intl, __str, __fill, __digits, true, __STATIC_CAST(string_type*, 0));
596 }
597
598 _STLP_END_NAMESPACE
599
600 #endif /* _STLP_MONETARY_C */
601
602 // Local Variables:
603 // mode:C++
604 // End: