null_padded_codecvt.hpp
来自「Boost provides free peer-reviewed portab」· HPP 代码 · 共 276 行
HPP
276 行
// (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)// (C) Copyright 2004-2007 Jonathan Turkanis// 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.)// See http://www.boost.org/libs/iostreams for documentation.// Contains the definitions of two codecvt facets useful for testing code // conversion. Both represent the "null padded" character encoding described as // follows. A wide character can be represented by the encoding if its value V// is within the range of an unsigned char. The first char of the sequence// representing V is V % 3 + 1. This is followed by V % 3 null characters, and// finally by V itself.// The first codecvt facet, null_padded_codecvt, is statefull, with state_type// equal to int.// The second codecvt facet, stateless_null_padded_codecvt, is stateless. At // each point in a conversion, no characters are consumed unless there is room // in the output sequence to write an entire multibyte sequence.#ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED#define BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED#include <boost/config.hpp> // NO_STDC_NAMESPACE#include <boost/iostreams/detail/codecvt_helper.hpp>#include <boost/iostreams/detail/config/wide_streams.hpp>#include <cstddef> // mbstate_t.#include <locale> // codecvt.#include <boost/integer_traits.hpp> // const_max.#ifdef BOOST_NO_STDC_NAMESPACE namespace std { using ::mbstate_t; }#endifnamespace boost { namespace iostreams { namespace test {//------------------Definition of null_padded_codecvt_state-------------------// class null_padded_codecvt_state {public: null_padded_codecvt_state(int val = 0) : val_(val) { } operator int() const { return val_; } int& val() { return val_; } const int& val() const { return val_; }private: int val_;};} } }BOOST_IOSTREAMS_CODECVT_SPEC(boost::iostreams::test::null_padded_codecvt_state)namespace boost { namespace iostreams { namespace test {//------------------Definition of null_padded_codevt--------------------------// //// state is initially 0. After a single character is consumed, state is set to // the number of characters in the current multibyte sequence and decremented// as each character is consumed until its value reaches 0 again.//class null_padded_codecvt : public iostreams::detail::codecvt_helper< wchar_t, char, null_padded_codecvt_state >{public: typedef null_padded_codecvt_state state_type;private: std::codecvt_base::result do_in( state_type& state, const char* first1, const char* last1, const char*& next1, wchar_t* first2, wchar_t* last2, wchar_t*& next2 ) const { using namespace std; if (state < 0 || state > 3) return codecvt_base::error; next1 = first1; next2 = first2; while (next2 != last2 && next1 != last1) { while (next1 != last1) { if (state == 0) { if (*next1 < 1 || *next1 > 3) return codecvt_base::error; state = *next1++; } else if (state == 1) { *next2++ = (unsigned char) *next1++; state = 0; break; } else { if (*next1++ != 0) return codecvt_base::error; --state.val(); } } } return next2 == last2 ? codecvt_base::ok : codecvt_base::partial; } std::codecvt_base::result do_out( state_type& state, const wchar_t* first1, const wchar_t* last1, const wchar_t*& next1, char* first2, char* last2, char*& next2 ) const { using namespace std; if (state < 0 || state > 3) return codecvt_base::error; next1 = first1; next2 = first2; while (next1 != last1 && next2 != last2) { while (next2 != last2) { if (state == 0) { if (*next1 > integer_traits<unsigned char>::const_max) return codecvt_base::noconv; state = *next1 % 3 + 1; *next2++ = static_cast<char>(state); } else if (state == 1) { state = 0; *next2++ = static_cast<unsigned char>(*next1++); break; } else { --state.val(); *next2++ = 0; } } } return next1 == last1 ? codecvt_base::ok : codecvt_base::partial; } std::codecvt_base::result do_unshift( state_type& state, char* /* first2 */, char* last2, char*& next2 ) const { using namespace std; next2 = last2; while (state.val()-- > 0) if (next2 != last2) *next2++ = 0; else return codecvt_base::partial; return codecvt_base::ok; } bool do_always_noconv() const throw() { return false; } int do_max_length() const throw() { return 4; } int do_encoding() const throw() { return -1; } int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type& state, const char* first1, const char* last1, std::size_t len2 ) const throw() { // Implementation should follow that of do_in(). int st = state; std::size_t result = 0; const char* next1 = first1; while (result < len2 && next1 != last1) { while (next1 != last1) { if (st == 0) { if (*next1 < 1 || *next1 > 3) return static_cast<int>(result); // error. st = *next1++; } else if (st == 1) { ++result; st = 0; break; } else { if (*next1++ != 0) return static_cast<int>(result); // error. --st; } } } return static_cast<int>(result); }};//------------------Definition of stateless_null_padded_codevt----------------//class stateless_null_padded_codecvt : public std::codecvt<wchar_t, char, std::mbstate_t> { std::codecvt_base::result do_in( state_type&, const char* first1, const char* last1, const char*& next1, wchar_t* first2, wchar_t* last2, wchar_t*& next2 ) const { using namespace std; for ( next1 = first1, next2 = first2; next1 != last1 && next2 != last2; ) { int len = (unsigned char) *next1; if (len < 1 || len > 3) return codecvt_base::error; if (last1 - next1 < len + 1) return codecvt_base::partial; ++next1; while (len-- > 1) if (*next1++ != 0) return codecvt_base::error; *next2++ = (unsigned char) *next1++; } return next1 == last1 && next2 == last2 ? codecvt_base::ok : codecvt_base::partial; } std::codecvt_base::result do_out( state_type&, const wchar_t* first1, const wchar_t* last1, const wchar_t*& next1, char* first2, char* last2, char*& next2 ) const { using namespace std; for ( next1 = first1, next2 = first2; next1 != last1 && next2 != last2; ) { if (*next1 > integer_traits<unsigned char>::const_max) return codecvt_base::noconv; int skip = *next1 % 3 + 2; if (last2 - next2 < skip) return codecvt_base::partial; *next2++ = static_cast<char>(--skip); while (skip-- > 1) *next2++ = 0; *next2++ = (unsigned char) *next1++; } return codecvt_base::ok; } std::codecvt_base::result do_unshift( state_type&, char* /* first2 */, char* /* last2 */, char*& /* next2 */ ) const { return std::codecvt_base::ok; } bool do_always_noconv() const throw() { return false; } int do_max_length() const throw() { return 4; } int do_encoding() const throw() { return -1; } int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER state_type&, const char* first1, const char* last1, std::size_t len2 ) const throw() { // Implementation should follow that of do_in(). std::size_t result = 0; for ( const char* next1 = first1; next1 != last1 && result < len2; ++result) { int len = (unsigned char) *next1; if (len < 1 || len > 3 || last1 - next1 < len + 1) return static_cast<int>(result); // error. ++next1; while (len-- > 1) if (*next1++ != 0) return static_cast<int>(result); // error. ++next1; } return static_cast<int>(result); } };} } } // End namespaces detail, iostreams, boost.#endif // #ifndef BOOST_IOSTREAMS_TEST_NULL_PADDED_CODECVT_HPP_INCLUDED
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?