2 // Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
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)
8 #define BOOST_LOCALE_SOURCE
12 #include <boost/locale/formatting.hpp>
13 #include <boost/locale/generator.hpp>
14 #include <boost/locale/encoding.hpp>
18 #include "../util/numeric.hpp"
19 #include "all_generator.hpp"
25 template<typename CharType
>
26 class time_put_from_base
: public std::time_put
<CharType
> {
28 time_put_from_base(std::locale
const &base
, size_t refs
= 0) :
29 std::time_put
<CharType
>(refs
),
33 typedef typename
std::time_put
<CharType
>::iter_type iter_type
;
35 virtual iter_type
do_put(iter_type out
,std::ios_base
&/*ios*/,CharType fill
,std::tm
const *tm
,char format
,char modifier
) const
37 std::basic_stringstream
<CharType
> ss
;
39 return std::use_facet
<std::time_put
<CharType
> >(base_
).put(out
,ss
,fill
,tm
,format
,modifier
);
45 class utf8_time_put_from_wide
: public std::time_put
<char> {
47 utf8_time_put_from_wide(std::locale
const &base
, size_t refs
= 0) :
48 std::time_put
<char>(refs
),
52 virtual iter_type
do_put(iter_type out
,std::ios_base
&/*ios*/,char fill
,std::tm
const *tm
,char format
,char modifier
= 0) const
54 std::basic_ostringstream
<wchar_t> wtmps
;
56 std::use_facet
<std::time_put
<wchar_t> >(base_
).put(wtmps
,wtmps
,wchar_t(fill
),tm
,wchar_t(format
),wchar_t(modifier
));
57 std::wstring wtmp
=wtmps
.str();
58 std::string
const tmp
= conv::from_utf
<wchar_t>(wtmp
,"UTF-8");
59 for(unsigned i
=0;i
<tmp
.size();i
++) {
68 class utf8_numpunct_from_wide
: public std::numpunct
<char> {
70 utf8_numpunct_from_wide(std::locale
const &base
,size_t refs
= 0) : std::numpunct
<char>(refs
)
72 typedef std::numpunct
<wchar_t> wfacet_type
;
73 wfacet_type
const &wfacet
= std::use_facet
<wfacet_type
>(base
);
75 truename_
= conv::from_utf
<wchar_t>(wfacet
.truename(),"UTF-8");
76 falsename_
= conv::from_utf
<wchar_t>(wfacet
.falsename(),"UTF-8");
78 wchar_t tmp_decimal_point
= wfacet
.decimal_point();
79 wchar_t tmp_thousands_sep
= wfacet
.thousands_sep();
80 std::string tmp_grouping
= wfacet
.grouping();
82 if( 32 <= tmp_thousands_sep
&& tmp_thousands_sep
<=126 &&
83 32 <= tmp_decimal_point
&& tmp_decimal_point
<=126)
85 thousands_sep_
= static_cast<char>(tmp_thousands_sep
);
86 decimal_point_
= static_cast<char>(tmp_decimal_point
);
87 grouping_
= tmp_grouping
;
89 else if(32 <= tmp_decimal_point
&& tmp_decimal_point
<=126 && tmp_thousands_sep
== 0xA0) {
90 // workaround common bug - substitute NBSP with ordinary space
92 decimal_point_
= static_cast<char>(tmp_decimal_point
);
93 grouping_
= tmp_grouping
;
95 else if(32 <= tmp_decimal_point
&& tmp_decimal_point
<=126)
98 decimal_point_
= static_cast<char>(tmp_decimal_point
);
99 grouping_
=std::string();
102 thousands_sep_
= ',';
103 decimal_point_
= '.';
104 grouping_
=std::string();
108 virtual char do_decimal_point() const
110 return decimal_point_
;
112 virtual char do_thousands_sep() const
114 return thousands_sep_
;
116 virtual std::string
do_grouping() const
120 virtual std::string
do_truename() const
124 virtual std::string
do_falsename() const
129 std::string truename_
;
130 std::string falsename_
;
133 std::string grouping_
;
138 class utf8_moneypunct_from_wide
: public std::moneypunct
<char,Intl
> {
140 utf8_moneypunct_from_wide(std::locale
const &base
,size_t refs
= 0) : std::moneypunct
<char,Intl
>(refs
)
142 typedef std::moneypunct
<wchar_t,Intl
> wfacet_type
;
143 wfacet_type
const &wfacet
= std::use_facet
<wfacet_type
>(base
);
145 curr_symbol_
= conv::from_utf
<wchar_t>(wfacet
.curr_symbol(),"UTF-8");
146 positive_sign_
= conv::from_utf
<wchar_t>(wfacet
.positive_sign(),"UTF-8");
147 negative_sign_
= conv::from_utf
<wchar_t>(wfacet
.negative_sign(),"UTF-8");
148 frac_digits_
= wfacet
.frac_digits();
149 pos_format_
= wfacet
.pos_format();
150 neg_format_
= wfacet
.neg_format();
152 wchar_t tmp_decimal_point
= wfacet
.decimal_point();
153 wchar_t tmp_thousands_sep
= wfacet
.thousands_sep();
154 std::string tmp_grouping
= wfacet
.grouping();
155 if( 32 <= tmp_thousands_sep
&& tmp_thousands_sep
<=126 &&
156 32 <= tmp_decimal_point
&& tmp_decimal_point
<=126)
158 thousands_sep_
= static_cast<char>(tmp_thousands_sep
);
159 decimal_point_
= static_cast<char>(tmp_decimal_point
);
160 grouping_
= tmp_grouping
;
162 else if(32 <= tmp_decimal_point
&& tmp_decimal_point
<=126 && tmp_thousands_sep
== 0xA0) {
163 // workaround common bug - substitute NBSP with ordinary space
164 thousands_sep_
= ' ';
165 decimal_point_
= static_cast<char>(tmp_decimal_point
);
166 grouping_
= tmp_grouping
;
168 else if(32 <= tmp_decimal_point
&& tmp_decimal_point
<=126)
171 decimal_point_
= static_cast<char>(tmp_decimal_point
);
172 grouping_
=std::string();
175 thousands_sep_
= ',';
176 decimal_point_
= '.';
177 grouping_
=std::string();
181 virtual char do_decimal_point() const
183 return decimal_point_
;
186 virtual char do_thousands_sep() const
188 return thousands_sep_
;
191 virtual std::string
do_grouping() const
196 virtual std::string
do_curr_symbol() const
200 virtual std::string
do_positive_sign () const
202 return positive_sign_
;
204 virtual std::string
do_negative_sign() const
206 return negative_sign_
;
209 virtual int do_frac_digits() const
214 virtual std::money_base::pattern
do_pos_format() const
219 virtual std::money_base::pattern
do_neg_format() const
227 std::string grouping_
;
228 std::string curr_symbol_
;
229 std::string positive_sign_
;
230 std::string negative_sign_
;
232 std::money_base::pattern pos_format_
,neg_format_
;
236 class utf8_numpunct
: public std::numpunct_byname
<char> {
238 typedef std::numpunct_byname
<char> base_type
;
239 utf8_numpunct(char const *name
,size_t refs
= 0) :
240 std::numpunct_byname
<char>(name
,refs
)
243 virtual char do_thousands_sep() const
245 unsigned char bs
= base_type::do_thousands_sep();
254 virtual std::string
do_grouping() const
256 unsigned char bs
= base_type::do_thousands_sep();
257 if(bs
> 127 && bs
!= 0xA0)
258 return std::string();
259 return base_type::do_grouping();
264 class utf8_moneypunct
: public std::moneypunct_byname
<char,Intl
> {
266 typedef std::moneypunct_byname
<char,Intl
> base_type
;
267 utf8_moneypunct(char const *name
,size_t refs
= 0) :
268 std::moneypunct_byname
<char,Intl
>(name
,refs
)
271 virtual char do_thousands_sep() const
273 unsigned char bs
= base_type::do_thousands_sep();
282 virtual std::string
do_grouping() const
284 unsigned char bs
= base_type::do_thousands_sep();
285 if(bs
> 127 && bs
!= 0xA0)
286 return std::string();
287 return base_type::do_grouping();
292 template<typename CharType
>
293 std::locale
create_basic_parsing(std::locale
const &in
,std::string
const &locale_name
)
295 std::locale tmp
= std::locale(in
,new std::numpunct_byname
<CharType
>(locale_name
.c_str()));
296 tmp
= std::locale(tmp
,new std::moneypunct_byname
<CharType
,true>(locale_name
.c_str()));
297 tmp
= std::locale(tmp
,new std::moneypunct_byname
<CharType
,false>(locale_name
.c_str()));
298 tmp
= std::locale(tmp
,new std::ctype_byname
<CharType
>(locale_name
.c_str()));
302 template<typename CharType
>
303 std::locale
create_basic_formatting(std::locale
const &in
,std::string
const &locale_name
)
305 std::locale tmp
= create_basic_parsing
<CharType
>(in
,locale_name
);
306 std::locale
base(locale_name
.c_str());
307 tmp
= std::locale(tmp
,new time_put_from_base
<CharType
>(base
));
312 std::locale
create_formatting( std::locale
const &in
,
313 std::string
const &locale_name
,
314 character_facet_type type
,
320 if(utf
== utf8_from_wide
) {
321 std::locale base
= std::locale(locale_name
.c_str());
323 std::locale tmp
= std::locale(in
,new utf8_time_put_from_wide(base
));
324 tmp
= std::locale(tmp
,new utf8_numpunct_from_wide(base
));
325 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<true>(base
));
326 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<false>(base
));
327 return std::locale(tmp
,new util::base_num_format
<char>());
329 else if(utf
== utf8_native
) {
330 std::locale base
= std::locale(locale_name
.c_str());
332 std::locale tmp
= std::locale(in
,new time_put_from_base
<char>(base
));
333 tmp
= std::locale(tmp
,new utf8_numpunct(locale_name
.c_str()));
334 tmp
= std::locale(tmp
,new utf8_moneypunct
<true>(locale_name
.c_str()));
335 tmp
= std::locale(tmp
,new utf8_moneypunct
<false>(locale_name
.c_str()));
336 return std::locale(tmp
,new util::base_num_format
<char>());
338 else if(utf
== utf8_native_with_wide
) {
339 std::locale base
= std::locale(locale_name
.c_str());
341 std::locale tmp
= std::locale(in
,new time_put_from_base
<char>(base
));
342 tmp
= std::locale(tmp
,new utf8_numpunct_from_wide(base
));
343 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<true>(base
));
344 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<false>(base
));
345 return std::locale(tmp
,new util::base_num_format
<char>());
349 std::locale tmp
= create_basic_formatting
<char>(in
,locale_name
);
350 tmp
= std::locale(tmp
,new util::base_num_format
<char>());
356 std::locale tmp
= create_basic_formatting
<wchar_t>(in
,locale_name
);
357 tmp
= std::locale(tmp
,new util::base_num_format
<wchar_t>());
360 #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
363 std::locale tmp
= create_basic_formatting
<char16_t
>(in
,locale_name
);
364 tmp
= std::locale(tmp
,new util::base_num_format
<char16_t
>());
368 #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
371 std::locale tmp
= create_basic_formatting
<char32_t
>(in
,locale_name
);
372 tmp
= std::locale(tmp
,new util::base_num_format
<char32_t
>());
381 std::locale
create_parsing( std::locale
const &in
,
382 std::string
const &locale_name
,
383 character_facet_type type
,
389 if(utf
== utf8_from_wide
) {
390 std::locale base
= std::locale::classic();
392 base
= std::locale(base
,new std::numpunct_byname
<wchar_t>(locale_name
.c_str()));
393 base
= std::locale(base
,new std::moneypunct_byname
<wchar_t,true>(locale_name
.c_str()));
394 base
= std::locale(base
,new std::moneypunct_byname
<wchar_t,false>(locale_name
.c_str()));
396 std::locale tmp
= std::locale(in
,new utf8_numpunct_from_wide(base
));
397 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<true>(base
));
398 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<false>(base
));
399 return std::locale(tmp
,new util::base_num_parse
<char>());
401 else if(utf
== utf8_native
) {
402 std::locale tmp
= std::locale(in
,new utf8_numpunct(locale_name
.c_str()));
403 tmp
= std::locale(tmp
,new utf8_moneypunct
<true>(locale_name
.c_str()));
404 tmp
= std::locale(tmp
,new utf8_moneypunct
<false>(locale_name
.c_str()));
405 return std::locale(tmp
,new util::base_num_parse
<char>());
407 else if(utf
== utf8_native_with_wide
) {
408 std::locale base
= std::locale(locale_name
.c_str());
410 std::locale tmp
= std::locale(in
,new utf8_numpunct_from_wide(base
));
411 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<true>(base
));
412 tmp
= std::locale(tmp
,new utf8_moneypunct_from_wide
<false>(base
));
413 return std::locale(tmp
,new util::base_num_parse
<char>());
417 std::locale tmp
= create_basic_parsing
<char>(in
,locale_name
);
418 tmp
= std::locale(in
,new util::base_num_parse
<char>());
424 std::locale tmp
= create_basic_parsing
<wchar_t>(in
,locale_name
);
425 tmp
= std::locale(in
,new util::base_num_parse
<wchar_t>());
428 #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
431 std::locale tmp
= create_basic_parsing
<char16_t
>(in
,locale_name
);
432 tmp
= std::locale(in
,new util::base_num_parse
<char16_t
>());
436 #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
439 std::locale tmp
= create_basic_parsing
<char32_t
>(in
,locale_name
);
440 tmp
= std::locale(in
,new util::base_num_parse
<char32_t
>());
456 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4