aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/libs/locale/src/std/collate.cpp
blob: 8eccdecb52a8913899e8f0d9b067894e11eaef70 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
// 
//  Copyright (c) 2009-2011 Artyom Beilis (Tonkikh) 
// 
//  Distributed under the Boost Software License, Version 1.0. (See 
//  accompanying file LICENSE_1_0.txt or copy at 
//  http://www.boost.org/LICENSE_1_0.txt) 
// 
#define BOOST_LOCALE_SOURCE 
#include <locale> 
#include <string> 
#include <ios> 
#include <boost/locale/encoding.hpp> 
#include "all_generator.hpp" 
 
namespace boost { 
namespace locale { 
namespace impl_std { 
 
class utf8_collator_from_wide : public std::collate<char> { 
public: 
    typedef std::collate<wchar_t> wfacet; 
    utf8_collator_from_wide(std::locale const &base,size_t refs = 0) :  
        std::collate<char>(refs), 
        base_(base) 
    { 
    } 
    virtual int do_compare(char const *lb,char const *le,char const *rb,char const *re) const 
    { 
        std::wstring l=conv::to_utf<wchar_t>(lb,le,"UTF-8"); 
        std::wstring r=conv::to_utf<wchar_t>(rb,re,"UTF-8"); 
        return std::use_facet<wfacet>(base_).compare(   l.c_str(),l.c_str()+l.size(), 
                                                        r.c_str(),r.c_str()+r.size()); 
    } 
    virtual long do_hash(char const *b,char const *e) const 
    { 
        std::wstring tmp=conv::to_utf<wchar_t>(b,e,"UTF-8"); 
        return std::use_facet<wfacet>(base_).hash(tmp.c_str(),tmp.c_str()+tmp.size()); 
    } 
    virtual std::string do_transform(char const *b,char const *e) const 
    { 
        std::wstring tmp=conv::to_utf<wchar_t>(b,e,"UTF-8"); 
        std::wstring wkey =  
            std::use_facet<wfacet>(base_).transform(tmp.c_str(),tmp.c_str()+tmp.size()); 
        std::string key; 
        if(sizeof(wchar_t)==2) 
            key.reserve(wkey.size()*2); 
        else 
            key.reserve(wkey.size()*3); 
        for(unsigned i=0;i<wkey.size();i++) { 
            if(sizeof(wchar_t)==2) { 
                uint16_t tv = static_cast<uint16_t>(wkey[i]); 
                key += char(tv >> 8); 
                key += char(tv & 0xFF); 
            } 
            else { // 4 
                uint32_t tv = static_cast<uint32_t>(wkey[i]); 
                // 21 bit 
                key += char((tv >> 16) & 0xFF); 
                key += char((tv >> 8) & 0xFF); 
                key += char(tv & 0xFF); 
            } 
        } 
        return key; 
    } 
private: 
    std::locale base_; 
}; 
 
std::locale create_collate( std::locale const &in, 
                            std::string const &locale_name, 
                            character_facet_type type, 
                            utf8_support utf) 
{ 
    switch(type) { 
    case char_facet: 
        { 
            if(utf == utf8_from_wide) { 
                std::locale base= 
                    std::locale(std::locale::classic(), 
                                new std::collate_byname<wchar_t>(locale_name.c_str())); 
                return std::locale(in,new utf8_collator_from_wide(base)); 
            } 
            else 
            { 
                return std::locale(in,new std::collate_byname<char>(locale_name.c_str())); 
            } 
        } 
 
    case wchar_t_facet: 
        return std::locale(in,new std::collate_byname<wchar_t>(locale_name.c_str())); 
 
    #ifdef BOOST_LOCALE_ENABLE_CHAR16_T 
    case char16_t_facet: 
        return std::locale(in,new std::collate_byname<char16_t>(locale_name.c_str())); 
    #endif 
 
    #ifdef BOOST_LOCALE_ENABLE_CHAR32_T 
    case char32_t_facet: 
        return std::locale(in,new std::collate_byname<char32_t>(locale_name.c_str())); 
    #endif 
    default: 
        return in; 
    } 
} 
 
 
} // impl_std 
} // locale  
} //boost 
 
 
 
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4