123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296 |
- #include <boost/detail/utf8_codecvt_facet.hpp>
- #include <cstdlib>
- #include <cassert>
- #include <boost/limits.hpp>
- #include <boost/config.hpp>
- #ifndef BOOST_NO_STD_WSTRING
- BOOST_UTF8_BEGIN_NAMESPACE
- namespace detail {
- inline const wchar_t * get_octet1_modifier_table() BOOST_NOEXCEPT
- {
- static const wchar_t octet1_modifier_table[] = {
- 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc
- };
- return octet1_modifier_table;
- }
- }
- BOOST_UTF8_DECL utf8_codecvt_facet::utf8_codecvt_facet(
- std::size_t no_locale_manage
- ) :
- std::codecvt<wchar_t, char, std::mbstate_t>(no_locale_manage)
- {}
- BOOST_UTF8_DECL utf8_codecvt_facet::~utf8_codecvt_facet()
- {}
- BOOST_UTF8_DECL std::codecvt_base::result utf8_codecvt_facet::do_in(
- std::mbstate_t& ,
- const char * from,
- const char * from_end,
- const char * & from_next,
- wchar_t * to,
- wchar_t * to_end,
- wchar_t * & to_next
- ) const {
-
-
-
-
-
-
-
-
- const wchar_t * const octet1_modifier_table = detail::get_octet1_modifier_table();
- while (from != from_end && to != to_end) {
-
- if (invalid_leading_octet(*from)) {
- from_next = from;
- to_next = to;
- return std::codecvt_base::error;
- }
-
-
- const int cont_octet_count = get_cont_octet_count(*from);
-
-
- wchar_t ucs_result =
- (unsigned char)(*from++) - octet1_modifier_table[cont_octet_count];
-
-
-
-
- int i = 0;
- while (i != cont_octet_count && from != from_end) {
-
- if (invalid_continuing_octet(*from)) {
- from_next = from;
- to_next = to;
- return std::codecvt_base::error;
- }
- ucs_result *= (1 << 6);
-
-
- ucs_result += (unsigned char)(*from++) - 0x80;
- ++i;
- }
-
- if (from == from_end && i != cont_octet_count) {
-
- from_next = from - (i + 1);
- to_next = to;
- return std::codecvt_base::partial;
- }
- *to++ = ucs_result;
- }
- from_next = from;
- to_next = to;
-
- if (from == from_end)
- return std::codecvt_base::ok;
- else
- return std::codecvt_base::partial;
- }
- BOOST_UTF8_DECL std::codecvt_base::result utf8_codecvt_facet::do_out(
- std::mbstate_t& ,
- const wchar_t * from,
- const wchar_t * from_end,
- const wchar_t * & from_next,
- char * to,
- char * to_end,
- char * & to_next
- ) const
- {
- const wchar_t * const octet1_modifier_table = detail::get_octet1_modifier_table();
- wchar_t max_wchar = (std::numeric_limits<wchar_t>::max)();
- while (from != from_end && to != to_end) {
-
- if (*from > max_wchar) {
- from_next = from;
- to_next = to;
- return std::codecvt_base::error;
- }
- int cont_octet_count = get_cont_octet_out_count(*from);
-
- int shift_exponent = cont_octet_count * 6;
-
- *to++ = static_cast<char>(octet1_modifier_table[cont_octet_count] +
- (unsigned char)(*from / (1 << shift_exponent)));
-
-
-
-
-
- int i = 0;
- while (i != cont_octet_count && to != to_end) {
- shift_exponent -= 6;
- *to++ = static_cast<char>(0x80 + ((*from / (1 << shift_exponent)) % (1 << 6)));
- ++i;
- }
-
- if (to == to_end && i != cont_octet_count) {
- from_next = from;
- to_next = to - (i + 1);
- return std::codecvt_base::partial;
- }
- ++from;
- }
- from_next = from;
- to_next = to;
-
- if (from == from_end)
- return std::codecvt_base::ok;
- else
- return std::codecvt_base::partial;
- }
- BOOST_UTF8_DECL int utf8_codecvt_facet::do_length(
- std::mbstate_t &,
- const char * from,
- const char * from_end,
- std::size_t max_limit
- ) const
- #if BOOST_WORKAROUND(__IBMCPP__, BOOST_TESTED_AT(600))
- throw()
- #endif
- {
- const char * from_next = from;
- for (std::size_t char_count = 0u; char_count < max_limit && from_next < from_end; ++char_count) {
- unsigned int octet_count = get_octet_count(*from_next);
-
- if (octet_count > static_cast<std::size_t>(from_end - from_next))
- break;
- from_next += octet_count;
- }
- return static_cast<int>(from_next - from);
- }
- BOOST_UTF8_DECL unsigned int utf8_codecvt_facet::get_octet_count(
- unsigned char lead_octet
- ) {
-
- if (lead_octet <= 0x7f) return 1;
-
- if (0xc0 <= lead_octet && lead_octet <= 0xdf) return 2;
- else if (0xe0 <= lead_octet && lead_octet <= 0xef) return 3;
- else if (0xf0 <= lead_octet && lead_octet <= 0xf7) return 4;
- else if (0xf8 <= lead_octet && lead_octet <= 0xfb) return 5;
- else return 6;
- }
- namespace detail {
- template<std::size_t s>
- inline int get_cont_octet_out_count_impl(wchar_t word) {
- if (word < 0x80) {
- return 0;
- }
- if (word < 0x800) {
- return 1;
- }
- return 2;
- }
- template<>
- inline int get_cont_octet_out_count_impl<4>(wchar_t word) {
- if (word < 0x80) {
- return 0;
- }
- if (word < 0x800) {
- return 1;
- }
-
-
-
-
-
-
- #if !defined(WCHAR_MAX)
- # error WCHAR_MAX not defined!
- #endif
-
- #if defined(_MSC_VER) && _MSC_VER <= 1310
- return 2;
- #elif WCHAR_MAX > 0x10000
- if (word < 0x10000) {
- return 2;
- }
- if (word < 0x200000) {
- return 3;
- }
- if (word < 0x4000000) {
- return 4;
- }
- return 5;
- #else
- return 2;
- #endif
- }
- }
- BOOST_UTF8_DECL int utf8_codecvt_facet::get_cont_octet_out_count(
- wchar_t word
- ) {
- return detail::get_cont_octet_out_count_impl<sizeof(wchar_t)>(word);
- }
- BOOST_UTF8_END_NAMESPACE
- #endif
|