facets_byname.cpp 38 KB

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