aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/restricted/boost/libs/locale/src/posix/converter.cpp
blob: bf8bc566d4f1ea0397577215e0451d7ee5b46921 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
//
//  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

#if defined(__FreeBSD__)
#include <xlocale.h>
#endif
#include <locale>
#include <stdexcept>
#include <boost/locale/generator.hpp>
#include <boost/locale/conversion.hpp>
#include <boost/locale/encoding.hpp>
#include <boost/shared_ptr.hpp>
#include <vector>
#include <string.h>
#include <wctype.h>
#include <ctype.h>
#include <langinfo.h>
#include "all_generator.hpp"

namespace boost {
namespace locale {
namespace impl_posix {

template<typename CharType>
struct case_traits;

template<>
struct case_traits<char> {
    static char lower(char c,locale_t lc)
    {
        return tolower_l(c,lc);
    }
    static char upper(char c,locale_t lc)
    {
        return toupper_l(c,lc);
    }
};

template<>
struct case_traits<wchar_t> {
    static wchar_t lower(wchar_t c,locale_t lc)
    {
        return towlower_l(c,lc);
    }
    static wchar_t upper(wchar_t c,locale_t lc)
    {
        return towupper_l(c,lc);
    }
};


template<typename CharType>
class std_converter : public converter<CharType> 
{
public:
    typedef CharType char_type;
    typedef std::basic_string<char_type> string_type;
    typedef std::ctype<char_type> ctype_type;
    std_converter(boost::shared_ptr<locale_t> lc,size_t refs = 0) : 
        converter<CharType>(refs),
        lc_(lc)
    {
    }
    virtual string_type convert(converter_base::conversion_type how,char_type const *begin,char_type const *end,int /*flags*/ = 0) const 
    {
        switch(how) {
        case converter_base::upper_case:
            {
                string_type res;
                res.reserve(end-begin);
                while(begin!=end) {
                    res+=case_traits<char_type>::upper(*begin++,*lc_);
                }
                return res;
            }
        case converter_base::lower_case:
        case converter_base::case_folding:
            {
                string_type res;
                res.reserve(end-begin);
                while(begin!=end) {
                    res+=case_traits<char_type>::lower(*begin++,*lc_);
                }
                return res;
            }
        default:
            return string_type(begin,end-begin);
        }
    }
private:
    boost::shared_ptr<locale_t> lc_;
};

class utf8_converter : public converter<char> {
public:
    utf8_converter(boost::shared_ptr<locale_t> lc,size_t refs = 0) : 
        converter<char>(refs),
        lc_(lc)
    {
    }
    virtual std::string convert(converter_base::conversion_type how,char const *begin,char const *end,int /*flags*/ = 0) const 
    {
        switch(how) {
        case upper_case:
            {
                std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8");
                std::wstring wres;
                wres.reserve(tmp.size());
                for(unsigned i=0;i<tmp.size();i++)
                    wres+=towupper_l(tmp[i],*lc_);
                return conv::from_utf<wchar_t>(wres,"UTF-8");
            }
            
        case lower_case:
        case case_folding:
            {
                std::wstring tmp = conv::to_utf<wchar_t>(begin,end,"UTF-8");
                std::wstring wres;
                wres.reserve(tmp.size());
                for(unsigned i=0;i<tmp.size();i++)
                    wres+=towlower_l(tmp[i],*lc_);
                return conv::from_utf<wchar_t>(wres,"UTF-8");
            }
        default:
            return std::string(begin,end-begin);
        }
    }
private:
    boost::shared_ptr<locale_t> lc_;
};

std::locale create_convert( std::locale const &in,
                            boost::shared_ptr<locale_t> lc,
                            character_facet_type type)
{
        switch(type) {
        case char_facet: 
            {
                std::string encoding = nl_langinfo_l(CODESET,*lc);
                for(unsigned i=0;i<encoding.size();i++)
                    if('A'<=encoding[i] && encoding[i]<='Z')
                        encoding[i]=encoding[i]-'A'+'a';
                if(encoding=="utf-8" || encoding=="utf8" || encoding=="utf_8") {
                    return std::locale(in,new utf8_converter(lc));
                }
                return std::locale(in,new std_converter<char>(lc));
            }
        case wchar_t_facet:
            return std::locale(in,new std_converter<wchar_t>(lc));
        default:
            return in;
        }
}


} // namespace impl_std
} // locale 
} // boost
// vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4