Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

826 lines
23 KiB

  1. // xlocmon internal header (from <locale>)
  2. #pragma once
  3. #ifndef _XLOCMON_
  4. #define _XLOCMON_
  5. #include <xiosbase>
  6. #pragma pack(push,8)
  7. #pragma warning(push,3)
  8. _STD_BEGIN
  9. // STRUCT money_base
  10. struct _CRTIMP2 money_base
  11. : public locale::facet
  12. { // ultimate base class for moneypunct
  13. enum
  14. { // constants for different format codes
  15. symbol = '$', sign = '+', space = ' ', value = 'v', none = 'x'};
  16. typedef int part;
  17. struct pattern
  18. { // four-part formats for monetary text
  19. char field[4];
  20. };
  21. money_base(size_t _Refs = 0)
  22. : locale::facet(_Refs)
  23. { // default constructor
  24. }
  25. };
  26. // TEMPLATE CLASS _Mpunct
  27. template<class _Elem>
  28. class _Mpunct
  29. : public money_base
  30. { // common base class for moneypunct<_Elem, false/true>
  31. public:
  32. typedef _Elem char_type;
  33. typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
  34. string_type;
  35. _Elem decimal_point() const
  36. { // return decimal point
  37. return (do_decimal_point());
  38. }
  39. _Elem thousands_sep() const
  40. { // return thousands separator
  41. return (do_thousands_sep());
  42. }
  43. string grouping() const
  44. { // return grouping string
  45. return (do_grouping());
  46. }
  47. string_type curr_symbol() const
  48. { // return currency symbol string
  49. return (do_curr_symbol());
  50. }
  51. string_type positive_sign() const
  52. { // return plus sign
  53. return (do_positive_sign());
  54. }
  55. string_type negative_sign() const
  56. { // return minus sign
  57. return (do_negative_sign());
  58. }
  59. int frac_digits() const
  60. { // return number of fraction digits
  61. return (do_frac_digits());
  62. }
  63. pattern pos_format() const
  64. { // return format for positive values
  65. return (do_pos_format());
  66. }
  67. pattern neg_format() const
  68. { // return format for negative values
  69. return (do_neg_format());
  70. }
  71. explicit _Mpunct(size_t _Refs, bool _Intl)
  72. : money_base(_Refs), _International(_Intl)
  73. { // construct from current locale
  74. _Init(_Locinfo());
  75. }
  76. _Mpunct(const _Locinfo& _Lobj, size_t _Refs, bool _Intl)
  77. : money_base(_Refs), _International(_Intl)
  78. { // construct from specified locale
  79. _Init(_Lobj);
  80. }
  81. _PROTECTED:
  82. virtual ~_Mpunct()
  83. { // destroy the object
  84. _Tidy();
  85. }
  86. protected:
  87. void _Init(const _Locinfo& _Lobj)
  88. { // initialize from _Lobj
  89. const lconv *_Ptr = _Lobj._Getlconv();
  90. _Grouping = 0;
  91. _Currencysign = 0;
  92. _Plussign = 0;
  93. _Minussign = 0;
  94. _TRY_BEGIN
  95. _Grouping = _MAKLOCSTR(char, _Ptr->mon_grouping, _Lobj._Getcvt());
  96. _Currencysign = _MAKLOCSTR(_Elem, _International
  97. ? _Ptr->int_curr_symbol : _Ptr->currency_symbol, _Lobj._Getcvt());
  98. _Plussign = _MAKLOCSTR(_Elem, 4 < (unsigned int)_Ptr->p_sign_posn
  99. ? "" : _Ptr->positive_sign, _Lobj._Getcvt());
  100. _Minussign = _MAKLOCSTR(_Elem, 4 < (unsigned int)_Ptr->n_sign_posn
  101. ? "-" : _Ptr->negative_sign, _Lobj._Getcvt());
  102. _CATCH_ALL
  103. _Tidy();
  104. _RERAISE;
  105. _CATCH_END
  106. _Decimalpoint = _WIDEN(_Elem, _Ptr->mon_decimal_point[0]);
  107. _Kseparator = _WIDEN(_Elem, _Ptr->mon_thousands_sep[0]);
  108. _Fracdigits = _International ? _Ptr->int_frac_digits
  109. : _Ptr->frac_digits;
  110. if (_Fracdigits < 0 || CHAR_MAX <= _Fracdigits)
  111. _Fracdigits = 0;
  112. _Makpat(_Plusformat, _Ptr->p_sep_by_space,
  113. _Ptr->p_cs_precedes, _Ptr->p_sign_posn);
  114. _Makpat(_Minusformat, _Ptr->n_sep_by_space,
  115. _Ptr->n_cs_precedes, _Ptr->n_sign_posn);
  116. }
  117. virtual _Elem do_decimal_point() const
  118. { // return decimal point
  119. return (_Decimalpoint);
  120. }
  121. virtual _Elem do_thousands_sep() const
  122. { // return thousands separator
  123. return (_Kseparator);
  124. }
  125. virtual string do_grouping() const
  126. { // return grouping string
  127. return (string(_Grouping));
  128. }
  129. virtual string_type do_curr_symbol() const
  130. { // return currency symbol string
  131. return (string_type(_Currencysign));
  132. }
  133. virtual string_type do_positive_sign() const
  134. { // return plus sign
  135. return (string_type(_Plussign));
  136. }
  137. virtual string_type do_negative_sign() const
  138. { // return minus sign
  139. return (string_type(_Minussign));
  140. }
  141. virtual int do_frac_digits() const
  142. { // return number of fraction digits
  143. return (_Fracdigits);
  144. }
  145. virtual pattern do_pos_format() const
  146. { // return format for positive values
  147. return (_Plusformat);
  148. }
  149. virtual pattern do_neg_format() const
  150. { // return format for negative values
  151. return (_Minusformat);
  152. }
  153. private:
  154. void _Makpat(pattern& _Pattern, unsigned int _Sepbyspace,
  155. unsigned int _Symbolprecedes, unsigned int _Signposition)
  156. { // make format pattern from locale information
  157. const char *_Ptr = _International || (_Sepbyspace & ~1) != 0
  158. || (_Symbolprecedes & ~1) != 0 || 4 < _Signposition
  159. ? "$+vx" // international or bad parameters
  160. : "+v$x" "+v$x" "v$+x" "v+$x" "v$+x"
  161. "+$vx" "+$vx" "$v+x" "+$vx" "$+vx"
  162. "+v $" "+v $" "v $+" "v+ $" "v $+"
  163. "+$ v" "+$ v" "$ v+" "+$ v" "$ +v"
  164. + (_Signposition * 4 // pick even/odd column
  165. + (_Symbolprecedes == 1 ? 20 : 0) // pick even/odd row
  166. + (_Sepbyspace == 1 ? 40 : 0)); // pick first/second half
  167. memcpy(_Pattern.field, _Ptr, 4);
  168. }
  169. void _Tidy()
  170. { // free all storage
  171. _DELETE_CRT_VEC((void *)_Grouping);
  172. _DELETE_CRT_VEC((void *)_Currencysign);
  173. _DELETE_CRT_VEC((void *)_Plussign);
  174. _DELETE_CRT_VEC((void *)_Minussign);
  175. }
  176. const char *_Grouping; // grouping string, "" for "C" locale
  177. _Elem _Decimalpoint; // decimal point, '\0' for "C" locale
  178. _Elem _Kseparator; // thousands separator, '\0' for "C" locale
  179. const _Elem *_Currencysign; // currency symbol, "" for "C" locale
  180. const _Elem *_Plussign; // plus sign, "" for "C" locale
  181. const _Elem *_Minussign; // minus sign, "-" for "C" locale
  182. int _Fracdigits; // number of fraction digits, 0 for "C" locale
  183. pattern _Plusformat; // positive format, "$+vx" for "C" locale
  184. pattern _Minusformat; // negative format, "$+vx" for "C" locale
  185. bool _International; // true if international format
  186. };
  187. // TEMPLATE CLASS moneypunct
  188. template<class _Elem,
  189. bool _Intl = false>
  190. class moneypunct
  191. : public _Mpunct<_Elem>
  192. { // facet for defining monetary punctuation text
  193. public:
  194. static const bool intl; // true if international
  195. static locale::id id; // unique facet id
  196. explicit moneypunct(size_t _Refs = 0)
  197. : _Mpunct<_Elem>(_Refs, _Intl)
  198. { // construct from current locale
  199. }
  200. moneypunct(const _Locinfo& _Lobj, size_t _Refs = 0)
  201. : _Mpunct<_Elem>(_Lobj, _Refs, _Intl)
  202. { // construct from specified locale
  203. }
  204. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  205. { // return locale category mask and construct standard facet
  206. if (_Ppf != 0 && *_Ppf == 0)
  207. *_Ppf = _NEW_CRT moneypunct<_Elem, _Intl>;
  208. return (_X_MONETARY);
  209. }
  210. };
  211. // STATIC moneypunct::intl OBJECT
  212. template<class _Elem,
  213. bool _Intl>
  214. const bool moneypunct<_Elem, _Intl>::intl = _Intl;
  215. // STATIC moneypunct::id OBJECT
  216. template<class _Elem,
  217. bool _Intl>
  218. locale::id moneypunct<_Elem, _Intl>::id;
  219. // TEMPLATE CLASS moneypunct_byname
  220. template<class _Elem,
  221. bool _Intl = false>
  222. class moneypunct_byname
  223. : public moneypunct<_Elem, _Intl>
  224. { // moneypunct for named locale
  225. public:
  226. explicit moneypunct_byname(const char *_Locname, size_t _Refs = 0)
  227. : moneypunct<_Elem, _Intl>(_Locinfo(_Locname), _Refs)
  228. { // construct for named locale
  229. }
  230. _PROTECTED:
  231. virtual ~moneypunct_byname()
  232. { // destroy the object
  233. }
  234. };
  235. // TEMPLATE CLASS money_get
  236. template<class _Elem,
  237. class _InIt = istreambuf_iterator<_Elem, char_traits<_Elem> > >
  238. class money_get
  239. : public locale::facet
  240. { // facet for converting text to encoded monetary amounts
  241. typedef moneypunct<_Elem, false> _Mypunct0;
  242. typedef moneypunct<_Elem, true> _Mypunct1;
  243. public:
  244. typedef _Elem char_type;
  245. typedef _InIt iter_type;
  246. typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
  247. string_type;
  248. _InIt get(_InIt _First, _InIt _Last, bool _Intl,
  249. ios_base& _Iosbase, ios_base::iostate& _State, long double& _Val) const
  250. { // get long double from [_First, _Last) into _Val
  251. return (do_get(_First, _Last, _Intl, _Iosbase, _State, _Val));
  252. }
  253. _InIt get(_InIt _First, _InIt _Last, bool _Intl,
  254. ios_base& _Iosbase, ios_base::iostate& _State, string_type& _Val) const
  255. { // get string_type from [_First, _Last) into _Val
  256. return (do_get(_First, _Last, _Intl, _Iosbase, _State, _Val));
  257. }
  258. static locale::id id; // unique facet id
  259. explicit money_get(size_t _Refs = 0)
  260. : locale::facet(_Refs)
  261. { // construct from current locale
  262. _Init(_Locinfo());
  263. }
  264. money_get(const _Locinfo& _Lobj, size_t _Refs = 0)
  265. : locale::facet(_Refs)
  266. { // construct from specified locale
  267. _Init(_Lobj);
  268. }
  269. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  270. { // return locale category mask and construct standard facet
  271. if (_Ppf != 0 && *_Ppf == 0)
  272. *_Ppf = _NEW_CRT money_get<_Elem, _InIt>;
  273. return (_X_MONETARY);
  274. }
  275. _PROTECTED:
  276. virtual ~money_get()
  277. { // destroy the object
  278. }
  279. protected:
  280. void _Init(const _Locinfo&)
  281. { // initialize from _Locinfo object (do nothing)
  282. }
  283. virtual _InIt do_get(_InIt _First, _InIt _Last, bool _Intl,
  284. ios_base& _Iosbase, ios_base::iostate& _State, long double& _Val) const
  285. { // get long double from [_First, _Last) into _Val
  286. string_type _Str = _Getmfld(_First, _Last, _Intl, _Iosbase);
  287. if (_First == _Last)
  288. _State |= ios_base::eofbit;
  289. if (_Str.size() == 0)
  290. _State |= ios_base::failbit; // _Getmfld failed
  291. else
  292. { // convert to char string, then to long double
  293. string _Str2;
  294. _Str2.reserve(_Str.size());
  295. for (size_t _Off = 0; _Off < _Str.size(); ++_Off)
  296. _Str2 += _NARROW(_Elem, _Str[_Off]);
  297. const char *_Eb = _Str2.c_str();
  298. char *_Ep;
  299. errno = 0;
  300. const long double _Ans = _Stold(_Eb, &_Ep, 0); // convert
  301. if (_Ep == _Eb || errno != 0)
  302. _State |= ios_base::failbit;
  303. else
  304. _Val = _Ans; // deliver value
  305. }
  306. return (_First);
  307. }
  308. virtual _InIt do_get(_InIt _First, _InIt _Last, bool _Intl,
  309. ios_base& _Iosbase, ios_base::iostate& _State, string_type& _Val) const
  310. { // get string_type from [_First, _Last) into _Val
  311. string_type _Str = _Getmfld(_First, _Last, _Intl, _Iosbase);
  312. if (_First == _Last)
  313. _State |= ios_base::eofbit;
  314. if (_Str.size() == 0)
  315. _State |= ios_base::failbit; // _Getmfld failed
  316. else
  317. _Val = _Str; // deliver value
  318. return (_First);
  319. }
  320. private:
  321. string_type _Getmfld(_InIt& _First, _InIt& _Last, bool _Intl,
  322. ios_base& _Iosbase) const
  323. { // get monetary field from [_First, _Last) into string_type
  324. const _Mpunct<_Elem> *_Pfac;
  325. if (_Intl)
  326. _Pfac = &_USE(_Iosbase.getloc(), _Mypunct1); // international
  327. else
  328. _Pfac = &_USE(_Iosbase.getloc(), _Mypunct0); // local
  329. const ctype<_Elem>& _Fac2 = _USE(_Iosbase.getloc(), ctype<_Elem>);
  330. bool _Bad = false, _Neg = false;
  331. string_type _Sign, _Val;
  332. const money_base::pattern _Pattern = _Pfac->neg_format();
  333. for (size_t _Off = 0; !_Bad && _Off < 4; ++_Off)
  334. switch (_Pattern.field[_Off])
  335. { // parse a format component
  336. case money_base::symbol:
  337. { // parse currency symbol
  338. string_type _Symbol = _Pfac->curr_symbol();
  339. typename string_type::const_iterator _Source;
  340. if (_Iosbase.flags() & ios_base::showbase)
  341. ; // showbase ==> mandatory currency symbol
  342. else if (_Off == 3 && _Sign.size() <= 1
  343. && (_First == _Last || *_First != *_Symbol.c_str()))
  344. _Symbol.erase(); // currency symbol optional at end
  345. for (_Source = _Symbol.begin();
  346. _First != _Last && _Source != _Symbol.end()
  347. && *_First == *_Source; ++_Source, ++_First)
  348. ; // still matching currency symbol
  349. if (_Source != _Symbol.end())
  350. _Bad = true; // currency symbol match failed
  351. break;
  352. }
  353. case money_base::sign: // parse sign
  354. if (_First == _Last)
  355. ; // assume no sign
  356. else if (0 < (_Pfac->positive_sign()).size()
  357. && _Pfac->positive_sign()[0] == *_First)
  358. { // match positive sign
  359. ++_First;
  360. _Sign = _Pfac->positive_sign();
  361. }
  362. else if (0 < (_Pfac->negative_sign()).size()
  363. && _Pfac->negative_sign()[0] == *_First)
  364. { // match negative sign
  365. ++_First;
  366. _Sign = _Pfac->negative_sign();
  367. _Neg = true;
  368. }
  369. break; // sign match can't fail
  370. case money_base::value:
  371. { // parse value field
  372. int _Fracdigseen = 0;
  373. int _Fracdigits = _Pfac->frac_digits();
  374. const string _Grouping = _Pfac->grouping();
  375. if (*_Grouping.c_str() <= '\0')
  376. while (_First != _Last
  377. && _Fac2.is(ctype_base::digit, *_First))
  378. _Val += *_First++; // no grouping, just gather digits
  379. else
  380. { // grouping specified, gather digits and group sizes
  381. const _Elem _Kseparator = _Pfac->thousands_sep();
  382. string _Groups((size_t)1, '\0');
  383. size_t _Group = 0;
  384. for (; _First != _Last; ++_First)
  385. if (_Fac2.is(ctype_base::digit, *_First))
  386. { // got a digit, add to group size
  387. _Val += *_First;
  388. if (_Groups[_Group] != CHAR_MAX)
  389. ++_Groups[_Group];
  390. }
  391. else if (_Groups[_Group] == '\0'
  392. || _Kseparator == (_Elem)0
  393. || *_First != _Kseparator)
  394. break; // not a group separator, done
  395. else
  396. { // add a new group to _Groups string
  397. _Groups.append((size_t)1, '\0');
  398. ++_Group;
  399. }
  400. if (_Group == 0)
  401. ; // no thousands separators seen
  402. else if ('\0' < _Groups[_Group])
  403. ++_Group; // add trailing group to group count
  404. else
  405. _Bad = true; // trailing separator, fail
  406. for (const char *_Pg = _Grouping.c_str();
  407. !_Bad && 0 < _Group; )
  408. if (*_Pg == CHAR_MAX)
  409. break; // end of grouping constraints to check
  410. else if (0 < --_Group && *_Pg != _Groups[_Group]
  411. || 0 == _Group && *_Pg < _Groups[_Group])
  412. _Bad = true; // bad group size, fail
  413. else if ('\0' < _Pg[1])
  414. ++_Pg; // group size okay, advance to next test
  415. if (_Bad)
  416. break; // bad grouping, give up
  417. }
  418. if (_First != _Last && *_First == _Pfac->decimal_point())
  419. { // seen decimal point, gather fraction digits
  420. while (++_First != _Last
  421. && _Fac2.is(ctype_base::digit, *_First))
  422. if (_Fracdigseen < _Fracdigits)
  423. _Val += *_First, ++_Fracdigseen;
  424. }
  425. if (_Val.size() == 0)
  426. _Bad = true; // fail if no elements parsed
  427. else
  428. for (; _Fracdigseen < _Fracdigits; ++_Fracdigseen)
  429. _Val += _WIDEN(_Elem, '0'); // pad out fraction
  430. break;
  431. }
  432. case money_base::space: // parse space
  433. if (_Off == 3)
  434. break; // ignore space format at end
  435. while (_First != _Last
  436. && _Fac2.is(ctype_base::space, *_First))
  437. ++_First; // space match can't fail
  438. }
  439. if (!_Bad && 1 < _Sign.size())
  440. { // match rest of sign string
  441. typename string_type::const_iterator _Source;
  442. for (_Source = _Sign.begin(); _First != _Last
  443. && ++_Source != _Sign.end() && *_First == *_Source; ++_First)
  444. ;
  445. if (_Source != _Sign.end())
  446. _Bad = true; // rest of sign doesn't match, fail
  447. }
  448. if (_Bad)
  449. _Val.erase(); // bad input, return empty string
  450. else if (_Neg)
  451. _Val.insert((size_t)0, (size_t)1, _WIDEN(_Elem, '-'));
  452. return (_Val);
  453. }
  454. };
  455. // STATIC money_get::id OBJECT
  456. template<class _Elem,
  457. class _InIt>
  458. locale::id money_get<_Elem, _InIt>::id;
  459. // TEMPLATE CLASS money_put
  460. template<class _Elem,
  461. class _OutIt = ostreambuf_iterator<_Elem, char_traits<_Elem> > >
  462. class money_put
  463. : public locale::facet
  464. { // facet for converting encoded monetary amounts to text
  465. typedef moneypunct<_Elem, false> _Mypunct0;
  466. typedef moneypunct<_Elem, true> _Mypunct1;
  467. public:
  468. typedef _Elem char_type;
  469. typedef _OutIt iter_type;
  470. typedef basic_string<_Elem, char_traits<_Elem>, allocator<_Elem> >
  471. string_type;
  472. _OutIt put(_OutIt _Dest, bool _Intl, ios_base& _Iosbase, _Elem _Fill,
  473. long double _Val) const
  474. { // put long double to _Dest
  475. return (do_put(_Dest, _Intl, _Iosbase, _Fill, _Val));
  476. }
  477. _OutIt put(_OutIt _Dest, bool _Intl, ios_base& _Iosbase, _Elem _Fill,
  478. const string_type& _Val) const
  479. { // put string_type to _Dest
  480. return (do_put(_Dest, _Intl, _Iosbase, _Fill, _Val));
  481. }
  482. static locale::id id; // unique facet id
  483. explicit money_put(size_t _Refs = 0)
  484. : locale::facet(_Refs)
  485. { // construct from current locale
  486. _Init(_Locinfo());
  487. }
  488. money_put(const _Locinfo& _Lobj, size_t _Refs = 0)
  489. : locale::facet(_Refs)
  490. { // construct from specified locale
  491. _Init(_Lobj);
  492. }
  493. static size_t __cdecl _Getcat(const locale::facet **_Ppf = 0)
  494. { // return locale category mask and construct standard facet
  495. if (_Ppf != 0 && *_Ppf == 0)
  496. *_Ppf = _NEW_CRT money_put<_Elem, _OutIt>;
  497. return (_X_MONETARY);
  498. }
  499. _PROTECTED:
  500. virtual ~money_put()
  501. { // destroy the object
  502. }
  503. protected:
  504. void _Init(const _Locinfo&)
  505. { // initialize from _Locinfo object (do nothing)
  506. }
  507. virtual _OutIt do_put(_OutIt _Dest, bool _Intl,
  508. ios_base& _Iosbase, _Elem _Fill, long double _Val) const
  509. { // put long double to _Dest
  510. bool _Negative = false;
  511. if (_Val < 0)
  512. _Negative = true, _Val = -_Val;
  513. size_t _Exp;
  514. for (_Exp = 0; 1e35 <= _Val && _Exp < 5000; _Exp += 10)
  515. _Val /= 1e10; // drop 10 zeros before decimal point
  516. string_type _Val2;
  517. char _Buf[40];
  518. int _Count = ::sprintf(_Buf, "%.0Lf",
  519. _Val); // convert to chars
  520. for (int _Off = 0; _Off < _Count; ++_Off)
  521. _Val2.append((typename string_type::size_type)1,
  522. _WIDEN(_Elem, _Buf[_Off])); // convert chars to elements
  523. _Val2.append(_Exp, _WIDEN(_Elem, '0'));
  524. return (_Putmfld(_Dest, _Intl, _Iosbase, _Fill, _Negative, _Val2));
  525. }
  526. virtual _OutIt do_put(_OutIt _Dest, bool _Intl,
  527. ios_base& _Iosbase, _Elem _Fill, const string_type& _Val) const
  528. { // put string_type to _Dest
  529. const ctype<_Elem>& _Fac = _USE(_Iosbase.getloc(), ctype<_Elem>);
  530. const _Elem *_Ptr = _Val.c_str();
  531. bool _Negative = false;
  532. if (*_Ptr == _WIDEN(_Elem, '-'))
  533. _Negative = true, ++_Ptr;
  534. size_t _Count;
  535. for (_Count = 0; _Fac.is(ctype_base::digit, _Ptr[_Count]); ++_Count)
  536. ; // count digits
  537. string_type _Val2(_Ptr, _Count);
  538. if (_Count == 0)
  539. _Val2.append((typename string_type::size_type)1,
  540. _WIDEN(_Elem, '0')); // replace empty digit string with '0'
  541. return (_Putmfld(_Dest, _Intl, _Iosbase, _Fill, _Negative, _Val2));
  542. }
  543. private:
  544. _OutIt _Putmfld(_OutIt _Dest, bool _Intl, ios_base& _Iosbase, _Elem _Fill,
  545. bool _Neg, string_type _Val) const
  546. { // put string_type with just digits to _Dest
  547. const _Mpunct<_Elem> *_Pfac;
  548. if (_Intl)
  549. _Pfac = &_USE(_Iosbase.getloc(), _Mypunct1); // international
  550. else
  551. _Pfac = &_USE(_Iosbase.getloc(), _Mypunct0); // local
  552. size_t _Fracdigits = _Pfac->frac_digits();
  553. const string _Grouping = _Pfac->grouping();
  554. if (_Fracdigits < _Val.size() && '\0' < *_Grouping.c_str())
  555. { // grouping specified, add thousands separators
  556. const _Elem _Kseparator = _Pfac->thousands_sep();
  557. const char *_Pg = _Grouping.c_str();
  558. size_t _Off = _Val.size() - _Fracdigits; // start of fraction
  559. while (*_Pg != CHAR_MAX && '\0' < *_Pg
  560. && (size_t)*_Pg < _Off)
  561. { // add a thousands separator, right to left
  562. _Val.insert(_Off -= *_Pg, (size_t)1, _Kseparator);
  563. if ('\0' < _Pg[1])
  564. ++_Pg; // not last group, advance
  565. }
  566. }
  567. money_base::pattern _Pattern;
  568. string_type _Sign;
  569. if (_Neg)
  570. { // negative value, choose appropriate format and sign
  571. _Pattern = _Pfac->neg_format();
  572. _Sign = _Pfac->negative_sign();
  573. }
  574. else
  575. { // positive value, choose appropriate format and sign
  576. _Pattern = _Pfac->pos_format();
  577. _Sign = _Pfac->positive_sign();
  578. }
  579. string_type _Symbol;
  580. if (_Iosbase.flags() & ios_base::showbase)
  581. _Symbol = _Pfac->curr_symbol(); // showbase ==> show symbol
  582. bool _Intern = false;
  583. size_t _Fillcount, _Off;
  584. for (_Fillcount = 0, _Off = 0; _Off < 4; ++_Off)
  585. switch (_Pattern.field[_Off])
  586. { // accumulate total length in _Fillcount
  587. case money_base::symbol: // count currency symbol size
  588. _Fillcount += _Symbol.size();
  589. break;
  590. case money_base::sign: // count sign size
  591. _Fillcount += _Sign.size();
  592. break;
  593. case money_base::value: // count value field size
  594. _Fillcount += _Val.size() + (0 < _Fracdigits ? 1 : 0)
  595. + (_Val.size() <= _Fracdigits
  596. ? _Fracdigits - _Val.size() + 1 : 0);
  597. break;
  598. case money_base::space: // count space size
  599. _Intern = true;
  600. }
  601. _Fillcount = _Iosbase.width() <= 0
  602. || (size_t)_Iosbase.width() <= _Fillcount
  603. ? 0 : (size_t)_Iosbase.width() - _Fillcount;
  604. ios_base::fmtflags _Afl =
  605. _Iosbase.flags() & ios_base::adjustfield;
  606. if (_Afl != ios_base::left
  607. && (_Afl != ios_base::internal || !_Intern))
  608. { // put leading fill
  609. _Dest = _Rep(_Dest, _Fill, _Fillcount);
  610. _Fillcount = 0;
  611. }
  612. for (_Off = 0; _Off < 4; ++_Off)
  613. switch (_Pattern.field[_Off])
  614. { // put components as specified by _Pattern
  615. case money_base::symbol: // put currency symbol
  616. _Dest = _Put(_Dest, _Symbol.begin(), _Symbol.size());
  617. break;
  618. case money_base::sign: // put sign
  619. if (0 < _Sign.size())
  620. _Dest = _Put(_Dest, _Sign.begin(), 1);
  621. break;
  622. case money_base::value: // put value field
  623. if (_Fracdigits == 0)
  624. _Dest = _Put(_Dest, _Val.begin(),
  625. _Val.size()); // no fraction part
  626. else if (_Val.size() <= _Fracdigits)
  627. { // put leading zero, all fraction digits
  628. *_Dest++ = _WIDEN(_Elem, '0');
  629. *_Dest++ = _Pfac->decimal_point();
  630. _Dest = _Rep(_Dest, _WIDEN(_Elem, '0'),
  631. _Fracdigits - _Val.size()); // insert zeros
  632. _Dest = _Put(_Dest, _Val.begin(), _Val.size());
  633. }
  634. else
  635. { // put both integer and fraction parts
  636. _Dest = _Put(_Dest, _Val.begin(),
  637. _Val.size() - _Fracdigits); // put integer part
  638. *_Dest++ = _Pfac->decimal_point();
  639. _Dest = _Put(_Dest, _Val.end() - _Fracdigits,
  640. _Fracdigits); // put fraction part
  641. }
  642. break;
  643. case money_base::space: // put any internal fill
  644. if (_Afl == ios_base::internal)
  645. { // put internal fill
  646. _Dest = _Rep(_Dest, _Fill, _Fillcount);
  647. _Fillcount = 0;
  648. }
  649. }
  650. if (1 < _Sign.size())
  651. _Dest = _Put(_Dest, _Sign.begin() + 1,
  652. _Sign.size() - 1); // put remainder of sign
  653. _Iosbase.width(0);
  654. return (_Rep(_Dest, _Fill, _Fillcount)); // put trailing fill
  655. }
  656. static _OutIt __cdecl _Put(_OutIt _Dest,
  657. typename string_type::const_iterator _Source, size_t _Count)
  658. { // put [_Source, _Source + _Count) to _Dest
  659. for (; 0 < _Count; --_Count, ++_Dest, ++_Source)
  660. *_Dest = *_Source;
  661. return (_Dest);
  662. }
  663. static _OutIt __cdecl _Rep(_OutIt _Dest, _Elem _Ch, size_t _Count)
  664. { // put _Count * _Ch to _Dest
  665. for (; 0 < _Count; --_Count, ++_Dest)
  666. *_Dest = _Ch;
  667. return (_Dest);
  668. }
  669. };
  670. // STATIC money_put::id OBJECT
  671. template<class _Elem,
  672. class _OutIt>
  673. locale::id money_put<_Elem, _OutIt>::id;
  674. #ifdef _DLL_CPPLIB
  675. #ifdef __FORCE_INSTANCE
  676. template class _CRTIMP2 moneypunct<char, true>;
  677. template class _CRTIMP2 moneypunct<char, false>;
  678. template class _CRTIMP2 moneypunct<wchar_t, true>;
  679. template class _CRTIMP2 moneypunct<wchar_t, false>;
  680. #ifdef _CRTBLD_NATIVE_WCHAR_T
  681. template class _CRTIMP2 moneypunct<unsigned short, true>;
  682. template class _CRTIMP2 moneypunct<unsigned short, false>;
  683. #endif
  684. template class _CRTIMP2 money_get<char,
  685. istreambuf_iterator<char, char_traits<char> > >;
  686. template class _CRTIMP2 money_get<wchar_t,
  687. istreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  688. #ifdef _CRTBLD_NATIVE_WCHAR_T
  689. template class _CRTIMP2 money_get<unsigned short,
  690. istreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
  691. #endif
  692. template class _CRTIMP2 money_put<char,
  693. ostreambuf_iterator<char, char_traits<char> > >;
  694. template class _CRTIMP2 money_put<wchar_t,
  695. ostreambuf_iterator<wchar_t, char_traits<wchar_t> > >;
  696. #ifdef _CRTBLD_NATIVE_WCHAR_T
  697. template class _CRTIMP2 money_put<unsigned short,
  698. ostreambuf_iterator<unsigned short, char_traits<unsigned short> > >;
  699. #endif
  700. #endif // __FORCE_INSTANCE
  701. #endif // _DLL_CPPLIB
  702. _STD_END
  703. #pragma warning(pop)
  704. #pragma pack(pop)
  705. #endif /* _XLOCMON_ */
  706. /*
  707. * Copyright (c) 1992-2001 by P.J. Plauger. ALL RIGHTS RESERVED.
  708. * Consult your license regarding permissions and restrictions.
  709. V3.10:0009 */