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 #if defined(__FreeBSD__)
10 #include <xlocale.h>
11 #endif
12 #include <locale>
13 #include <locale.h>
14 #include <string.h>
15 #include <wchar.h>
16 #include <string>
17 #include <stdexcept>
18 #include <ios>
19 #include <vector>
20 #include <boost/locale/generator.hpp>
21 #include "../shared/mo_hash.hpp"
22
23 #include "all_generator.hpp"
24
25 namespace boost {
26 namespace locale {
27 namespace impl_posix {
28
29 template<typename CharType>
30 struct coll_traits;
31
32 template<>
33 struct coll_traits<char> {
xfrmboost::locale::impl_posix::coll_traits34 static size_t xfrm(char *out,char const *in,size_t n,locale_t l)
35 {
36 return strxfrm_l(out,in,n,l);
37 }
collboost::locale::impl_posix::coll_traits38 static size_t coll(char const *left,char const *right,locale_t l)
39 {
40 return strcoll_l(left,right,l);
41 }
42 };
43
44 template<>
45 struct coll_traits<wchar_t> {
xfrmboost::locale::impl_posix::coll_traits46 static size_t xfrm(wchar_t *out,wchar_t const *in,size_t n,locale_t l)
47 {
48 return wcsxfrm_l(out,in,n,l);
49 }
collboost::locale::impl_posix::coll_traits50 static size_t coll(wchar_t const *left,wchar_t const *right,locale_t l)
51 {
52 return wcscoll_l(left,right,l);
53 }
54 };
55
56 template<typename CharType>
57 class collator : public std::collate<CharType> {
58 public:
59 typedef CharType char_type;
60 typedef std::basic_string<char_type> string_type;
collator(boost::shared_ptr<locale_t> l,size_t refs=0)61 collator(boost::shared_ptr<locale_t> l,size_t refs = 0) :
62 std::collate<CharType>(refs),
63 lc_(l)
64 {
65 }
~collator()66 virtual ~collator()
67 {
68 }
do_compare(char_type const * lb,char_type const * le,char_type const * rb,char_type const * re) const69 virtual int do_compare(char_type const *lb,char_type const *le,char_type const *rb,char_type const *re) const
70 {
71 string_type left(lb,le-lb);
72 string_type right(rb,re-rb);
73 int res = coll_traits<char_type>::coll(left.c_str(),right.c_str(),*lc_);
74 if(res < 0)
75 return -1;
76 if(res > 0)
77 return 1;
78 return 0;
79 }
do_hash(char_type const * b,char_type const * e) const80 virtual long do_hash(char_type const *b,char_type const *e) const
81 {
82 string_type s(do_transform(b,e));
83 char const *begin = reinterpret_cast<char const *>(s.c_str());
84 char const *end = begin + s.size() * sizeof(char_type);
85 return gnu_gettext::pj_winberger_hash_function(begin,end);
86 }
do_transform(char_type const * b,char_type const * e) const87 virtual string_type do_transform(char_type const *b,char_type const *e) const
88 {
89 string_type s(b,e-b);
90 std::vector<char_type> buf((e-b)*2+1);
91 size_t n = coll_traits<char_type>::xfrm(&buf.front(),s.c_str(),buf.size(),*lc_);
92 if(n>buf.size()) {
93 buf.resize(n);
94 coll_traits<char_type>::xfrm(&buf.front(),s.c_str(),n,*lc_);
95 }
96 return string_type(&buf.front(),n);
97 }
98 private:
99 boost::shared_ptr<locale_t> lc_;
100 };
101
102
create_collate(std::locale const & in,boost::shared_ptr<locale_t> lc,character_facet_type type)103 std::locale create_collate( std::locale const &in,
104 boost::shared_ptr<locale_t> lc,
105 character_facet_type type)
106 {
107 switch(type) {
108 case char_facet:
109 return std::locale(in,new collator<char>(lc));
110 case wchar_t_facet:
111 return std::locale(in,new collator<wchar_t>(lc));
112 default:
113 return in;
114 }
115 }
116
117
118 } // impl_std
119 } // locale
120 } //boost
121
122
123
124 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
125