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 #define BOOST_LOCALE_SOURCE
9 #include <locale>
10 #include <string>
11 #include <ios>
12 #include <boost/locale/formatting.hpp>
13 #include <boost/locale/generator.hpp>
14 #include <boost/locale/encoding.hpp>
15 #include <boost/shared_ptr.hpp>
16 #include <sstream>
17 #include <stdlib.h>
18 #include <time.h>
19 #include <string.h>
20 #include <wctype.h>
21 #include <ctype.h>
22 
23 #include "all_generator.hpp"
24 #include "api.hpp"
25 #include "../util/numeric.hpp"
26 
27 namespace boost {
28 namespace locale {
29 namespace impl_win {
30     namespace {
31 
write_it(std::ostreambuf_iterator<wchar_t> out,std::wstring const & s)32         std::ostreambuf_iterator<wchar_t> write_it(std::ostreambuf_iterator<wchar_t> out,std::wstring const &s)
33         {
34             for(size_t i=0;i<s.size();i++)
35                 *out++ = s[i];
36             return out;
37         }
38 
write_it(std::ostreambuf_iterator<char> out,std::wstring const & s)39         std::ostreambuf_iterator<char> write_it(std::ostreambuf_iterator<char> out,std::wstring const &s)
40         {
41             std::string tmp = conv::from_utf(s,"UTF-8");
42             for(size_t i=0;i<tmp.size();i++)
43                 *out++ = tmp[i];
44             return out;
45         }
46     }
47 
48 
49 template<typename CharType>
50 class num_format : public util::base_num_format<CharType>
51 {
52 public:
53     typedef typename std::num_put<CharType>::iter_type iter_type;
54     typedef std::basic_string<CharType> string_type;
55     typedef CharType char_type;
56 
num_format(winlocale const & lc,size_t refs=0)57     num_format(winlocale const &lc,size_t refs = 0) :
58         util::base_num_format<CharType>(refs),
59         lc_(lc)
60     {
61     }
62 private:
63 
64     virtual
do_format_currency(bool,iter_type out,std::ios_base & ios,char_type fill,long double val) const65     iter_type do_format_currency(bool /*intl*/,iter_type out,std::ios_base &ios,char_type fill,long double val) const
66     {
67         if(lc_.is_c()) {
68             std::locale loc = ios.getloc();
69             int digits = std::use_facet<std::moneypunct<char_type> >(loc).frac_digits();
70             while(digits > 0) {
71                 val*=10;
72                 digits --;
73             }
74             std::ios_base::fmtflags f=ios.flags();
75             ios.flags(f | std::ios_base::showbase);
76             out = std::use_facet<std::money_put<char_type> >(loc).put(out,false,ios,fill,val);
77             ios.flags(f);
78             return out;
79         }
80         else {
81             std::wstring cur = wcsfmon_l(val,lc_);
82             return write_it(out,cur);
83         }
84     }
85 
86 private:
87     winlocale lc_;
88 
89 };  /// num_format
90 
91 template<typename CharType>
92 class time_put_win : public std::time_put<CharType> {
93 public:
time_put_win(winlocale const & lc,size_t refs=0)94     time_put_win(winlocale const &lc, size_t refs = 0) :
95         std::time_put<CharType>(refs),
96         lc_(lc)
97     {
98     }
~time_put_win()99     virtual ~time_put_win()
100     {
101     }
102     typedef typename std::time_put<CharType>::iter_type iter_type;
103     typedef CharType char_type;
104     typedef std::basic_string<char_type> string_type;
105 
do_put(iter_type out,std::ios_base &,CharType,std::tm const * tm,char format,char) const106     virtual iter_type do_put(   iter_type out,
107                                 std::ios_base &/*ios*/,
108                                 CharType /*fill*/,
109                                 std::tm const *tm,
110                                 char format,
111                                 char /*modifier*/) const
112     {
113         return write_it(out,wcsftime_l(format,tm,lc_));
114     }
115 
116 private:
117     winlocale lc_;
118 };
119 
120 
121 template<typename CharType>
122 class num_punct_win : public std::numpunct<CharType> {
123 public:
124     typedef std::basic_string<CharType> string_type;
num_punct_win(winlocale const & lc,size_t refs=0)125     num_punct_win(winlocale const &lc,size_t refs = 0) :
126         std::numpunct<CharType>(refs)
127     {
128         numeric_info np = wcsnumformat_l(lc) ;
129         if(sizeof(CharType) == 1 && np.thousands_sep == L"\xA0")
130             np.thousands_sep=L" ";
131 
132         to_str(np.thousands_sep,thousands_sep_);
133         to_str(np.decimal_point,decimal_point_);
134         grouping_ = np.grouping;
135         if(thousands_sep_.size() > 1)
136             grouping_ = std::string();
137         if(decimal_point_.size() > 1)
138             decimal_point_ = CharType('.');
139     }
140 
to_str(std::wstring & s1,std::wstring & s2)141     void to_str(std::wstring &s1,std::wstring &s2)
142     {
143         s2.swap(s1);
144     }
145 
to_str(std::wstring & s1,std::string & s2)146     void to_str(std::wstring &s1,std::string &s2)
147     {
148         s2=conv::from_utf(s1,"UTF-8");
149     }
do_decimal_point() const150     virtual CharType do_decimal_point() const
151     {
152         return *decimal_point_.c_str();
153     }
do_thousands_sep() const154     virtual CharType do_thousands_sep() const
155     {
156         return *thousands_sep_.c_str();
157     }
do_grouping() const158     virtual std::string do_grouping() const
159     {
160         return grouping_;
161     }
do_truename() const162     virtual string_type do_truename() const
163     {
164         static const char t[]="true";
165         return string_type(t,t+sizeof(t)-1);
166     }
do_falsename() const167     virtual string_type do_falsename() const
168     {
169         static const char t[]="false";
170         return string_type(t,t+sizeof(t)-1);
171     }
172 private:
173     string_type decimal_point_;
174     string_type thousands_sep_;
175     std::string grouping_;
176 };
177 
178 template<typename CharType>
create_formatting_impl(std::locale const & in,winlocale const & lc)179 std::locale create_formatting_impl(std::locale const &in,winlocale const &lc)
180 {
181     if(lc.is_c()) {
182         std::locale tmp(in,new std::numpunct_byname<CharType>("C"));
183         tmp=std::locale(tmp,new std::time_put_byname<CharType>("C"));
184         tmp = std::locale(tmp,new num_format<CharType>(lc));
185         return tmp;
186     }
187     else {
188         std::locale tmp(in,new num_punct_win<CharType>(lc));
189         tmp = std::locale(tmp,new time_put_win<CharType>(lc));
190         tmp = std::locale(tmp,new num_format<CharType>(lc));
191         return tmp;
192     }
193 }
194 
195 template<typename CharType>
create_parsing_impl(std::locale const & in,winlocale const & lc)196 std::locale create_parsing_impl(std::locale const &in,winlocale const &lc)
197 {
198     std::numpunct<CharType> *np = 0;
199     if(lc.is_c())
200         np = new std::numpunct_byname<CharType>("C");
201     else
202         np = new num_punct_win<CharType>(lc);
203     std::locale tmp(in,np);
204     tmp = std::locale(tmp,new util::base_num_parse<CharType>());
205     return tmp;
206 }
207 
208 
create_formatting(std::locale const & in,winlocale const & lc,character_facet_type type)209 std::locale create_formatting(  std::locale const &in,
210                                 winlocale const &lc,
211                                 character_facet_type type)
212 {
213         switch(type) {
214         case char_facet:
215             return create_formatting_impl<char>(in,lc);
216         case wchar_t_facet:
217             return create_formatting_impl<wchar_t>(in,lc);
218         default:
219             return in;
220         }
221 }
222 
create_parsing(std::locale const & in,winlocale const & lc,character_facet_type type)223 std::locale create_parsing( std::locale const &in,
224                             winlocale const &lc,
225                             character_facet_type type)
226 {
227         switch(type) {
228         case char_facet:
229             return create_parsing_impl<char>(in,lc);
230         case wchar_t_facet:
231             return create_parsing_impl<wchar_t>(in,lc);
232         default:
233             return in;
234         }
235 }
236 
237 
238 
239 } // impl_std
240 } // locale
241 } //boost
242 
243 
244 
245 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
246