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 "all_generator.hpp"
14
15 namespace boost {
16 namespace locale {
17 namespace impl_std {
18
19 class utf8_collator_from_wide : public std::collate<char> {
20 public:
21 typedef std::collate<wchar_t> wfacet;
utf8_collator_from_wide(std::locale const & base,size_t refs=0)22 utf8_collator_from_wide(std::locale const &base,size_t refs = 0) :
23 std::collate<char>(refs),
24 base_(base)
25 {
26 }
do_compare(char const * lb,char const * le,char const * rb,char const * re) const27 virtual int do_compare(char const *lb,char const *le,char const *rb,char const *re) const
28 {
29 std::wstring l=conv::to_utf<wchar_t>(lb,le,"UTF-8");
30 std::wstring r=conv::to_utf<wchar_t>(rb,re,"UTF-8");
31 return std::use_facet<wfacet>(base_).compare( l.c_str(),l.c_str()+l.size(),
32 r.c_str(),r.c_str()+r.size());
33 }
do_hash(char const * b,char const * e) const34 virtual long do_hash(char const *b,char const *e) const
35 {
36 std::wstring tmp=conv::to_utf<wchar_t>(b,e,"UTF-8");
37 return std::use_facet<wfacet>(base_).hash(tmp.c_str(),tmp.c_str()+tmp.size());
38 }
do_transform(char const * b,char const * e) const39 virtual std::string do_transform(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 =
43 std::use_facet<wfacet>(base_).transform(tmp.c_str(),tmp.c_str()+tmp.size());
44 std::string key;
45 if(sizeof(wchar_t)==2)
46 key.reserve(wkey.size()*2);
47 else
48 key.reserve(wkey.size()*3);
49 for(unsigned i=0;i<wkey.size();i++) {
50 if(sizeof(wchar_t)==2) {
51 uint16_t tv = static_cast<uint16_t>(wkey[i]);
52 key += char(tv >> 8);
53 key += char(tv & 0xFF);
54 }
55 else { // 4
56 uint32_t tv = static_cast<uint32_t>(wkey[i]);
57 // 21 bit
58 key += char((tv >> 16) & 0xFF);
59 key += char((tv >> 8) & 0xFF);
60 key += char(tv & 0xFF);
61 }
62 }
63 return key;
64 }
65 private:
66 std::locale base_;
67 };
68
create_collate(std::locale const & in,std::string const & locale_name,character_facet_type type,utf8_support utf)69 std::locale create_collate( std::locale const &in,
70 std::string const &locale_name,
71 character_facet_type type,
72 utf8_support utf)
73 {
74 switch(type) {
75 case char_facet:
76 {
77 if(utf == utf8_from_wide) {
78 std::locale base=
79 std::locale(std::locale::classic(),
80 new std::collate_byname<wchar_t>(locale_name.c_str()));
81 return std::locale(in,new utf8_collator_from_wide(base));
82 }
83 else
84 {
85 return std::locale(in,new std::collate_byname<char>(locale_name.c_str()));
86 }
87 }
88
89 case wchar_t_facet:
90 return std::locale(in,new std::collate_byname<wchar_t>(locale_name.c_str()));
91
92 #ifdef BOOST_LOCALE_ENABLE_CHAR16_T
93 case char16_t_facet:
94 return std::locale(in,new std::collate_byname<char16_t>(locale_name.c_str()));
95 #endif
96
97 #ifdef BOOST_LOCALE_ENABLE_CHAR32_T
98 case char32_t_facet:
99 return std::locale(in,new std::collate_byname<char32_t>(locale_name.c_str()));
100 #endif
101 default:
102 return in;
103 }
104 }
105
106
107 } // impl_std
108 } // locale
109 } //boost
110
111
112
113 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
114