1 // (C) Copyright 2008 CodeRage, LLC (turkanis at coderage dot com)
2 // (C) Copyright 2003-2007 Jonathan Turkanis
3 // Distributed under the Boost Software License, Version 1.0. (See accompanying
4 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt.)
5 
6 // See http://www.boost.org/libs/iostreams for documentation.
7 
8 // Contains the definition of the template codecvt_helper, useful for
9 // defining specializations of std::codecvt where state_type != mbstate_t.
10 // Compensates for the fact that some standard library implementations
11 // do not derive the primiary codecvt template from locale::facet or
12 // provide the correct member types and functions.
13 
14 // Usage:
15 //
16 // // In global namespace:
17 // BOOST_IOSTREAMS_CODECVT_SPEC(mystate)
18 //
19 // // In user namespace:
20 // template<typename Intern, typename Extern>
21 // struct mycodecvt : codecvt_helper<Intern, Extern, State> { ... };
22 //
23 // // Or:
24 // struct mycodecvt : codecvt_helper<wchar_t, char, State> { ... };
25 //
26 // Etc.
27 
28 #ifndef BOOST_IOSTREAMS_DETAIL_CODECVT_HELPER_HPP_INCLUDED
29 #define BOOST_IOSTREAMS_DETAIL_CODECVT_HELPER_HPP_INCLUDED
30 
31 #if defined(_MSC_VER) && (_MSC_VER >= 1020)
32 # pragma once
33 #endif
34 
35 #include <boost/config.hpp>  // Put size_t in std, BOOST_MSVC, Dinkum.
36 #include <boost/detail/workaround.hpp>
37 #include <algorithm>         // min.
38 #include <cstddef>           // size_t.
39 #include <locale>            // locale, codecvt_base, codecvt.
40 #include <boost/iostreams/detail/config/codecvt.hpp>
41 
42 //------------------Definition of traits--------------------------------------//
43 
44 namespace boost { namespace iostreams { namespace detail {
45 
46 #if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) //-----------------------//
47 
48 template<typename T>
49 struct codecvt_intern { typedef typename T::intern_type type; };
50 
51 template<typename T>
52 struct codecvt_extern { typedef typename T::extern_type type; };
53 
54 #else // #if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) //--------------//
55 
56 template<typename T>
57 struct codecvt_intern { typedef typename T::from_type type; };
58 
59 template<typename T>
60 struct codecvt_extern { typedef typename T::to_type type; };
61 
62 #endif // #if !BOOST_WORKAROUND(BOOST_DINKUMWARE_STDLIB, == 1) //-------------//
63 
64 template<typename T>
65 struct codecvt_state { typedef typename T::state_type type; };
66 
67 } } } // End namespaces detail, iostreams, boost.
68 
69 //------------------Definition of codecvt_impl--------------------------------//
70 
71 #if defined(BOOST_IOSTREAMS_NO_PRIMARY_CODECVT_DEFINITION) || \
72     defined(BOOST_IOSTREAMS_EMPTY_PRIMARY_CODECVT_DEFINITION) || \
73     defined(BOOST_IOSTREAMS_NO_LOCALE) \
74     /**/
75 
76 namespace boost { namespace iostreams { namespace detail {
77 
78 template<typename Intern, typename Extern, typename State>
79 struct codecvt_impl : std::locale::facet, std::codecvt_base {
80 public:
81     typedef Intern  intern_type;
82     typedef Extern  extern_type;
83     typedef State   state_type;
84 
codecvt_implboost::iostreams::detail::codecvt_impl85     codecvt_impl(std::size_t refs = 0) : std::locale::facet(refs) { }
86 
87     std::codecvt_base::result
inboost::iostreams::detail::codecvt_impl88     in( State& state, const Extern* first1, const Extern* last1,
89         const Extern*& next1, Intern* first2, Intern* last2,
90         Intern*& next2 ) const
91     {
92         return do_in(state, first1, last1, next1, first2, last2, next2);
93     }
94 
95     std::codecvt_base::result
outboost::iostreams::detail::codecvt_impl96     out( State& state, const Intern* first1, const Intern* last1,
97          const Intern*& next1, Extern* first2, Extern* last2,
98          Extern*& next2 ) const
99     {
100         return do_out(state, first1, last1, next1, first2, last2, next2);
101     }
102 
103     std::codecvt_base::result
unshiftboost::iostreams::detail::codecvt_impl104     unshift(State& state, Extern* first2, Extern* last2, Extern*& next2) const
105     {
106         return do_unshift(state, first2, last2, next2);
107     }
108 
always_noconvboost::iostreams::detail::codecvt_impl109     bool always_noconv() const throw() { return do_always_noconv(); }
110 
max_lengthboost::iostreams::detail::codecvt_impl111     int max_length() const throw() { return do_max_length(); }
112 
encodingboost::iostreams::detail::codecvt_impl113     int encoding() const throw() { return do_encoding(); }
114 
lengthboost::iostreams::detail::codecvt_impl115     int length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER State& state,
116                 const Extern* first1, const Extern* last1,
117                 std::size_t len2 ) const throw()
118     {
119         return do_length(state, first1, last1, len2);
120     }
121 protected:
122     std::codecvt_base::result
do_inboost::iostreams::detail::codecvt_impl123     virtual do_in( State&, const Extern*, const Extern*, const Extern*&,
124                    Intern*, Intern*, Intern*& ) const
125     {
126         return std::codecvt_base::noconv;
127     }
128 
129     std::codecvt_base::result
do_outboost::iostreams::detail::codecvt_impl130     virtual do_out( State&, const Intern*, const Intern*, const Intern*&,
131                     Extern*, Extern*, Extern*& ) const
132     {
133         return std::codecvt_base::noconv;
134     }
135 
136     std::codecvt_base::result
do_unshiftboost::iostreams::detail::codecvt_impl137     virtual do_unshift(State&, Extern*, Extern*, Extern*&) const
138     {
139         return std::codecvt_base::ok;
140     }
141 
do_always_noconvboost::iostreams::detail::codecvt_impl142     virtual bool do_always_noconv() const throw() { return true; }
143 
do_max_lengthboost::iostreams::detail::codecvt_impl144     virtual int do_max_length() const throw() { return 1; }
145 
do_encodingboost::iostreams::detail::codecvt_impl146     virtual int do_encoding() const throw() { return 1; }
147 
do_lengthboost::iostreams::detail::codecvt_impl148     virtual int do_length( BOOST_IOSTREAMS_CODECVT_CV_QUALIFIER State&,
149                            const Extern* first1, const Extern* last1,
150                            std::size_t len2 ) const throw()
151     {
152         return (std::min)(static_cast<std::size_t>(last1 - first1), len2);
153     }
154 };
155 
156 } } } // End namespaces detail, iostreams, boost.
157 
158 #endif // no primary codecvt definition, empty definition.
159 
160 //------------------Definition of BOOST_IOSTREAMS_CODECVT_SPEC----------------//
161 
162 #if defined(BOOST_IOSTREAMS_NO_PRIMARY_CODECVT_DEFINITION) || \
163     defined(BOOST_IOSTREAMS_EMPTY_PRIMARY_CODECVT_DEFINITION) \
164     /**/
165 # ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
166 #  define BOOST_IOSTREAMS_CODECVT_SPEC(state) \
167     namespace std { \
168         template<typename Intern, typename Extern> \
169         class codecvt<Intern, Extern, state> \
170             : public ::boost::iostreams::detail::codecvt_impl< \
171                          Intern, Extern, state \
172                      > \
173         { \
174         public: \
175             codecvt(std::size_t refs = 0) \
176                 : ::boost::iostreams::detail::codecvt_impl< \
177                       Intern, Extern, state \
178                   >(refs) \
179                 { } \
180             static std::locale::id id; \
181         }; \
182         template<typename Intern, typename Extern> \
183         std::locale::id codecvt<Intern, Extern, state>::id; \
184     } \
185     /**/
186 # else
187 #  define BOOST_IOSTREAMS_CODECVT_SPEC(state) \
188     namespace std { \
189         template<> \
190         class codecvt<wchar_t, char, state> \
191             : public ::boost::iostreams::detail::codecvt_impl< \
192                          wchar_t, char, state \
193                      > \
194         { \
195         public: \
196             codecvt(std::size_t refs = 0) \
197                 : ::boost::iostreams::detail::codecvt_impl< \
198                       wchar_t, char, state \
199                   >(refs) \
200                 { } \
201             static std::locale::id id; \
202         }; \
203         template<> \
204         std::locale::id codecvt<wchar_t, char, state>::id; \
205     } \
206     /**/
207 # endif
208 #else
209 # define BOOST_IOSTREAMS_CODECVT_SPEC(state)
210 #endif // no primary codecvt definition, or empty definition.
211 
212 namespace boost { namespace iostreams { namespace detail {
213 
214 //------------------Definition of codecvt_helper------------------------------//
215 
216 template<typename Intern, typename Extern, typename State>
217 struct codecvt_helper : std::codecvt<Intern, Extern, State> {
218     typedef Intern  intern_type;
219     typedef Extern  extern_type;
220     typedef State   state_type;
codecvt_helperboost::iostreams::detail::codecvt_helper221     codecvt_helper(std::size_t refs = 0)
222     #if !defined(BOOST_IOSTREAMS_NO_CODECVT_CTOR_FROM_SIZE_T)
223         : std::codecvt<Intern, Extern, State>(refs)
224     #else
225         : std::codecvt<Intern, Extern, State>()
226     #endif
227         { }
228 #ifdef BOOST_IOSTREAMS_NO_CODECVT_MAX_LENGTH
max_lengthboost::iostreams::detail::codecvt_helper229     int max_length() const throw() { return do_max_length(); }
230 protected:
do_max_lengthboost::iostreams::detail::codecvt_helper231     virtual int do_max_length() const throw() { return 1; }
232 #endif
233 };
234 
235 } } } // End namespaces detail, iostreams, boost.
236 
237 #endif // #ifndef BOOST_IOSTREAMS_DETAIL_CODECVT_HELPER_HPP_INCLUDED
238