1//
2// Copyright (c) 2009-2011 Artyom Beilis (Tonkikh)
3//
4// Distributed under the Boost Software License, Version 1.0.
5// https://www.boost.org/LICENSE_1_0.txt
6
7#include <boost/locale/generator.hpp>
8#if defined(__FreeBSD__)
9# include <xlocale.h>
10#endif
11#include <clocale>
12#include <cstring>
13#include <ios>
14#include <locale>
15#include <stdexcept>
16#include <string>
17#include <vector>
18#include <wchar.h>
19
20#include "boost/locale/posix/all_generator.hpp"
21#include "boost/locale/shared/mo_hash.hpp"
22
23namespace boost { namespace locale { namespace impl_posix {
24
25 template<typename CharType>
26 struct coll_traits;
27
28 template<>
29 struct coll_traits<char> {
30 static size_t xfrm(char* out, const char* in, size_t n, locale_t l) { return strxfrm_l(dest: out, src: in, n: n, l: l); }
31 static size_t coll(const char* left, const char* right, locale_t l) { return strcoll_l(s1: left, s2: right, l: l); }
32 };
33
34 template<>
35 struct coll_traits<wchar_t> {
36 static size_t xfrm(wchar_t* out, const wchar_t* in, size_t n, locale_t l) { return wcsxfrm_l(s1: out, s2: in, n: n, loc: l); }
37 static size_t coll(const wchar_t* left, const wchar_t* right, locale_t l) { return wcscoll_l(s1: left, s2: right, loc: l); }
38 };
39
40 template<typename CharType>
41 class collator : public std::collate<CharType> {
42 public:
43 typedef std::basic_string<CharType> string_type;
44 collator(std::shared_ptr<locale_t> l, size_t refs = 0) : std::collate<CharType>(refs), lc_(std::move(l)) {}
45
46 int do_compare(const CharType* lb, const CharType* le, const CharType* rb, const CharType* re) const override
47 {
48 string_type left(lb, le - lb);
49 string_type right(rb, re - rb);
50 int res = coll_traits<CharType>::coll(left.c_str(), right.c_str(), *lc_);
51 if(res < 0)
52 return -1;
53 if(res > 0)
54 return 1;
55 return 0;
56 }
57 long do_hash(const CharType* b, const CharType* e) const override
58 {
59 string_type s(do_transform(b, e));
60 const char* begin = reinterpret_cast<const char*>(s.c_str());
61 const char* end = begin + s.size() * sizeof(CharType);
62 return gnu_gettext::pj_winberger_hash_function(begin, end);
63 }
64 string_type do_transform(const CharType* b, const CharType* e) const override
65 {
66 string_type s(b, e - b);
67 std::vector<CharType> buf((e - b) * 2 + 1);
68 size_t n = coll_traits<CharType>::xfrm(buf.data(), s.c_str(), buf.size(), *lc_);
69 if(n > buf.size()) {
70 buf.resize(n);
71 coll_traits<CharType>::xfrm(buf.data(), s.c_str(), n, *lc_);
72 }
73 return string_type(buf.data(), n);
74 }
75
76 private:
77 std::shared_ptr<locale_t> lc_;
78 };
79
80 std::locale create_collate(const std::locale& in, std::shared_ptr<locale_t> lc, char_facet_t type)
81 {
82 switch(type) {
83 case char_facet_t::nochar: break;
84 case char_facet_t::char_f: return std::locale(in, new collator<char>(std::move(lc)));
85 case char_facet_t::wchar_f: return std::locale(in, new collator<wchar_t>(std::move(lc)));
86#ifdef __cpp_char8_t
87 case char_facet_t::char8_f: break; // std-facet not available (yet)
88#endif
89#ifdef BOOST_LOCALE_ENABLE_CHAR16_T
90 case char_facet_t::char16_f: return std::locale(in, new collator<char16_t>(std::move(lc)));
91#endif
92#ifdef BOOST_LOCALE_ENABLE_CHAR32_T
93 case char_facet_t::char32_f: return std::locale(in, new collator<char32_t>(std::move(lc)));
94#endif
95 }
96 return in;
97 }
98
99}}} // namespace boost::locale::impl_posix
100

source code of boost/libs/locale/src/boost/locale/posix/collate.cpp