blob: fe63315183fd64290eb0cd6e123630e628fc9924 [file] [log] [blame]
//
// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_LOCALE_PREDEFINED_FORMATTERS_HPP_INCLUDED
#define BOOST_LOCALE_PREDEFINED_FORMATTERS_HPP_INCLUDED
#include <string>
#include <memory>
#include <boost/cstdint.hpp>
#include <boost/thread.hpp>
#include <boost/locale/config.hpp>
#include <unicode/locid.h>
#include <unicode/numfmt.h>
#include <unicode/rbnf.h>
#include <unicode/datefmt.h>
#include <unicode/smpdtfmt.h>
#include <unicode/decimfmt.h>
namespace boost {
namespace locale {
namespace impl_icu {
class icu_formatters_cache : public std::locale::facet {
public:
static std::locale::id id;
icu_formatters_cache(icu::Locale const &locale) :
locale_(locale)
{
static const icu::DateFormat::EStyle styles[4] = {
icu::DateFormat::kShort,
icu::DateFormat::kMedium,
icu::DateFormat::kLong,
icu::DateFormat::kFull
};
for(int i=0;i<4;i++) {
std::auto_ptr<icu::DateFormat> fmt(icu::DateFormat::createDateInstance(styles[i],locale));
icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get());
if(sfmt) {
sfmt->toPattern(date_format_[i]);
}
}
for(int i=0;i<4;i++) {
std::auto_ptr<icu::DateFormat> fmt(icu::DateFormat::createTimeInstance(styles[i],locale));
icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get());
if(sfmt) {
sfmt->toPattern(time_format_[i]);
}
}
for(int i=0;i<4;i++) {
for(int j=0;j<4;j++) {
std::auto_ptr<icu::DateFormat> fmt(
icu::DateFormat::createDateTimeInstance(styles[i],styles[j],locale));
icu::SimpleDateFormat *sfmt = dynamic_cast<icu::SimpleDateFormat*>(fmt.get());
if(sfmt) {
sfmt->toPattern(date_time_format_[i][j]);
}
}
}
}
typedef enum {
fmt_number,
fmt_sci,
fmt_curr_nat,
fmt_curr_iso,
fmt_per,
fmt_spell,
fmt_ord,
fmt_count
} fmt_type;
icu::NumberFormat *number_format(fmt_type type) const
{
icu::NumberFormat *ptr = number_format_[type].get();
if(ptr)
return ptr;
UErrorCode err=U_ZERO_ERROR;
std::auto_ptr<icu::NumberFormat> ap;
switch(type) {
case fmt_number:
ap.reset(icu::NumberFormat::createInstance(locale_,err));
break;
case fmt_sci:
ap.reset(icu::NumberFormat::createScientificInstance(locale_,err));
break;
#if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 402
#if U_ICU_VERSION_MAJOR_NUM*100 + U_ICU_VERSION_MINOR_NUM >= 408
case fmt_curr_nat:
ap.reset(icu::NumberFormat::createInstance(locale_,UNUM_CURRENCY,err));
break;
case fmt_curr_iso:
ap.reset(icu::NumberFormat::createInstance(locale_,UNUM_CURRENCY_ISO,err));
break;
#else
case fmt_curr_nat:
ap.reset(icu::NumberFormat::createInstance(locale_,icu::NumberFormat::kCurrencyStyle,err));
break;
case fmt_curr_iso:
ap.reset(icu::NumberFormat::createInstance(locale_,icu::NumberFormat::kIsoCurrencyStyle,err));
break;
#endif
#else
case fmt_curr_nat:
case fmt_curr_iso:
ap.reset(icu::NumberFormat::createCurrencyInstance(locale_,err));
break;
#endif
case fmt_per:
ap.reset(icu::NumberFormat::createPercentInstance(locale_,err));
break;
case fmt_spell:
ap.reset(new icu::RuleBasedNumberFormat(icu::URBNF_SPELLOUT,locale_,err));
break;
case fmt_ord:
ap.reset(new icu::RuleBasedNumberFormat(icu::URBNF_ORDINAL,locale_,err));
break;
default:
throw std::runtime_error("locale::internal error should not get there");
}
test(err);
ptr = ap.get();
number_format_[type].reset(ap.release());
return ptr;
}
void test(UErrorCode err) const
{
if(U_FAILURE(err))
throw std::runtime_error("Failed to create a formatter");
}
icu::UnicodeString date_format_[4];
icu::UnicodeString time_format_[4];
icu::UnicodeString date_time_format_[4][4];
icu::SimpleDateFormat *date_formatter() const
{
icu::SimpleDateFormat *p=date_formatter_.get();
if(p)
return p;
std::auto_ptr<icu::DateFormat> fmt(icu::DateFormat::createDateTimeInstance(
icu::DateFormat::kMedium,
icu::DateFormat::kMedium,
locale_));
if(dynamic_cast<icu::SimpleDateFormat *>(fmt.get())) {
p = static_cast<icu::SimpleDateFormat *>(fmt.release());
date_formatter_.reset(p);
}
return p;
}
private:
mutable boost::thread_specific_ptr<icu::NumberFormat> number_format_[fmt_count];
mutable boost::thread_specific_ptr<icu::SimpleDateFormat> date_formatter_;
icu::Locale locale_;
};
} // namespace impl_icu
} // namespace locale
} // namespace boost
#endif
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4