blob: 3beaf942a9e7bcd886c01d395ff6ccbccb4b29a8 [file] [log] [blame]
//
// 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 <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