ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
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.
 
 
 
 
 
 

187 lines
6.6 KiB

  1. //
  2. // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See
  5. // accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt)
  7. //
  8. #ifndef BOOSTER_LOCALE_PREDEFINED_FORMATTERS_H_INCLUDED
  9. #define BOOSTER_LOCALE_PREDEFINED_FORMATTERS_H_INCLUDED
  10. #include <string>
  11. #include <booster/auto_ptr_inc.h>
  12. #include <booster/cstdint.h>
  13. #include <booster/thread.h>
  14. #include <booster/config.h>
  15. #include <unicode/locid.h>
  16. #include <unicode/numfmt.h>
  17. #include <unicode/rbnf.h>
  18. #include <unicode/datefmt.h>
  19. #include <unicode/smpdtfmt.h>
  20. #include <unicode/decimfmt.h>
  21. namespace booster {
  22. namespace locale {
  23. namespace impl_icu {
  24. class icu_formatters_cache : public std::locale::facet {
  25. public:
  26. static std::locale::id id;
  27. icu_formatters_cache(icu::Locale const &locale) :
  28. locale_(locale)
  29. {
  30. static const icu::DateFormat::EStyle styles[4] = {
  31. icu::DateFormat::kShort,
  32. icu::DateFormat::kMedium,
  33. icu::DateFormat::kLong,
  34. icu::DateFormat::kFull
  35. };
  36. for(int i=0;i<4;i++) {
  37. std::auto_ptr<icu::DateFormat> fmt(icu::DateFormat::createDateInstance(styles[i],locale));
  38. icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get());
  39. if(sfmt) {
  40. sfmt->toPattern(date_format_[i]);
  41. }
  42. }
  43. for(int i=0;i<4;i++) {
  44. std::auto_ptr<icu::DateFormat> fmt(icu::DateFormat::createTimeInstance(styles[i],locale));
  45. icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get());
  46. if(sfmt) {
  47. sfmt->toPattern(time_format_[i]);
  48. }
  49. }
  50. for(int i=0;i<4;i++) {
  51. for(int j=0;j<4;j++) {
  52. std::auto_ptr<icu::DateFormat> fmt(
  53. icu::DateFormat::createDateTimeInstance(styles[i],styles[j],locale));
  54. icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get());
  55. if(sfmt) {
  56. sfmt->toPattern(date_time_format_[i][j]);
  57. }
  58. }
  59. }
  60. }
  61. typedef enum {
  62. fmt_number,
  63. fmt_sci,
  64. fmt_curr_nat,
  65. fmt_curr_iso,
  66. fmt_per,
  67. fmt_spell,
  68. fmt_ord,
  69. fmt_count
  70. } fmt_type;
  71. icu::NumberFormat *number_format(fmt_type type) const
  72. {
  73. icu::NumberFormat *ptr = number_format_[type].get();
  74. if(ptr)
  75. return ptr;
  76. UErrorCode err=U_ZERO_ERROR;
  77. std::auto_ptr<icu::NumberFormat> ap;
  78. switch(type) {
  79. case fmt_number:
  80. ap.reset(icu::NumberFormat::createInstance(locale_,err));
  81. break;
  82. case fmt_sci:
  83. ap.reset(icu::NumberFormat::createScientificInstance(locale_,err));
  84. break;
  85. #if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 402
  86. #if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 408
  87. case fmt_curr_nat:
  88. ap.reset(icu::NumberFormat::createInstance(locale_,UNUM_CURRENCY,err));
  89. break;
  90. case fmt_curr_iso:
  91. ap.reset(icu::NumberFormat::createInstance(locale_,UNUM_CURRENCY_ISO,err));
  92. break;
  93. #else
  94. case fmt_curr_nat:
  95. ap.reset(icu::NumberFormat::createInstance(locale_,icu::NumberFormat::kCurrencyStyle,err));
  96. break;
  97. case fmt_curr_iso:
  98. ap.reset(icu::NumberFormat::createInstance(locale_,icu::NumberFormat::kIsoCurrencyStyle,err));
  99. break;
  100. #endif
  101. #else
  102. case fmt_curr_nat:
  103. case fmt_curr_iso:
  104. ap.reset(icu::NumberFormat::createCurrencyInstance(locale_,err));
  105. break;
  106. #endif
  107. case fmt_per:
  108. ap.reset(icu::NumberFormat::createPercentInstance(locale_,err));
  109. break;
  110. case fmt_spell:
  111. ap.reset(new icu::RuleBasedNumberFormat(icu::URBNF_SPELLOUT,locale_,err));
  112. break;
  113. case fmt_ord:
  114. ap.reset(new icu::RuleBasedNumberFormat(icu::URBNF_ORDINAL,locale_,err));
  115. break;
  116. default:
  117. throw booster::runtime_error("locale::internal error should not get there");
  118. }
  119. test(err);
  120. ptr = ap.get();
  121. number_format_[type].reset(ap.release());
  122. return ptr;
  123. }
  124. void test(UErrorCode err) const
  125. {
  126. if(U_FAILURE(err))
  127. throw booster::runtime_error("Failed to create a formatter");
  128. }
  129. icu::UnicodeString date_format_[4];
  130. icu::UnicodeString time_format_[4];
  131. icu::UnicodeString date_time_format_[4][4];
  132. icu::SimpleDateFormat *date_formatter() const
  133. {
  134. icu::SimpleDateFormat *p=date_formatter_.get();
  135. if(p)
  136. return p;
  137. std::auto_ptr<icu::DateFormat> fmt(icu::DateFormat::createDateTimeInstance(
  138. icu::DateFormat::kMedium,
  139. icu::DateFormat::kMedium,
  140. locale_));
  141. if(dynamic_cast<icu::SimpleDateFormat *>(fmt.get())) {
  142. p = static_cast<icu::SimpleDateFormat *>(fmt.release());
  143. date_formatter_.reset(p);
  144. }
  145. return p;
  146. }
  147. private:
  148. mutable booster::thread_specific_ptr<icu::NumberFormat> number_format_[fmt_count];
  149. mutable booster::thread_specific_ptr<icu::SimpleDateFormat> date_formatter_;
  150. icu::Locale locale_;
  151. };
  152. } // namespace impl_icu
  153. } // namespace locale
  154. } // namespace boost
  155. #endif
  156. // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4