123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- // (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; }
- #endif
- namespace 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
|