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/encoding.hpp>
13 #include <boost/locale/generator.hpp>
14 #include "api.hpp"
15 #include "../shared/mo_hash.hpp"
16
17 namespace boost {
18 namespace locale {
19 namespace impl_win {
20
21 class utf8_collator : public collator<char> {
22 public:
utf8_collator(winlocale lc,size_t refs=0)23 utf8_collator(winlocale lc,size_t refs = 0) :
24 collator<char>(refs),
25 lc_(lc)
26 {
27 }
do_compare(collator_base::level_type level,char const * lb,char const * le,char const * rb,char const * re) const28 virtual int do_compare(collator_base::level_type level,char const *lb,char const *le,char const *rb,char const *re) const
29 {
30 std::wstring l=conv::to_utf<wchar_t>(lb,le,"UTF-8");
31 std::wstring r=conv::to_utf<wchar_t>(rb,re,"UTF-8");
32 return wcscoll_l(level,l.c_str(),l.c_str()+l.size(),r.c_str(),r.c_str()+r.size(),lc_);
33 }
do_hash(collator_base::level_type level,char const * b,char const * e) const34 virtual long do_hash(collator_base::level_type level,char const *b,char const *e) const
35 {
36 std::string key = do_transform(level,b,e);
37 return gnu_gettext::pj_winberger_hash_function(key.c_str(),key.c_str() + key.size());
38 }
do_transform(collator_base::level_type level,char const * b,char const * e) const39 virtual std::string do_transform(collator_base::level_type level,char const *b,char const *e) const
40 {
41 std::wstring tmp=conv::to_utf<wchar_t>(b,e,"UTF-8");
42 std::wstring wkey = wcsxfrm_l(level,tmp.c_str(),tmp.c_str()+tmp.size(),lc_);
43 std::string key;
44 if(sizeof(wchar_t)==2)
45 key.reserve(wkey.size()*2);
46 else
47 key.reserve(wkey.size()*3);
48 for(unsigned i=0;i<wkey.size();i++) {
49 if(sizeof(wchar_t)==2) {
50 uint16_t tv = static_cast<uint16_t>(wkey[i]);
51 key += char(tv >> 8);
52 key += char(tv & 0xFF);
53 }
54 else { // 4
55 uint32_t tv = static_cast<uint32_t>(wkey[i]);
56 // 21 bit
57 key += char((tv >> 16) & 0xFF);
58 key += char((tv >> 8) & 0xFF);
59 key += char(tv & 0xFF);
60 }
61 }
62 return key;
63 }
64 private:
65 winlocale lc_;
66 };
67
68
69 class utf16_collator : public collator<wchar_t> {
70 public:
71 typedef std::collate<wchar_t> wfacet;
utf16_collator(winlocale lc,size_t refs=0)72 utf16_collator(winlocale lc,size_t refs = 0) :
73 collator<wchar_t>(refs),
74 lc_(lc)
75 {
76 }
do_compare(collator_base::level_type level,wchar_t const * lb,wchar_t const * le,wchar_t const * rb,wchar_t const * re) const77 virtual int do_compare(collator_base::level_type level,wchar_t const *lb,wchar_t const *le,wchar_t const *rb,wchar_t const *re) const
78 {
79 return wcscoll_l(level,lb,le,rb,re,lc_);
80 }
do_hash(collator_base::level_type level,wchar_t const * b,wchar_t const * e) const81 virtual long do_hash(collator_base::level_type level,wchar_t const *b,wchar_t const *e) const
82 {
83 std::wstring key = do_transform(level,b,e);
84 char const *begin = reinterpret_cast<char const *>(key.c_str());
85 char const *end = begin + key.size()*sizeof(wchar_t);
86 return gnu_gettext::pj_winberger_hash_function(begin,end);
87 }
do_transform(collator_base::level_type level,wchar_t const * b,wchar_t const * e) const88 virtual std::wstring do_transform(collator_base::level_type level,wchar_t const *b,wchar_t const *e) const
89 {
90 return wcsxfrm_l(level,b,e,lc_);
91 }
92 private:
93 winlocale lc_;
94 };
95
96
create_collate(std::locale const & in,winlocale const & lc,character_facet_type type)97 std::locale create_collate( std::locale const &in,
98 winlocale const &lc,
99 character_facet_type type)
100 {
101 if(lc.is_c()) {
102 switch(type) {
103 case char_facet:
104 return std::locale(in,new std::collate_byname<char>("C"));
105 case wchar_t_facet:
106 return std::locale(in,new std::collate_byname<wchar_t>("C"));
107 }
108 }
109 else {
110 switch(type) {
111 case char_facet:
112 return std::locale(in,new utf8_collator(lc));
113 case wchar_t_facet:
114 return std::locale(in,new utf16_collator(lc));
115 }
116 }
117 return in;
118 }
119
120
121 } // impl_std
122 } // locale
123 } //boost
124
125
126
127 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
128