1 // char_conv.hh
2 // This file is part of libpbe; see http://anyterm.org/
3 // (C) 2008 Philip Endecott
4 
5 // Distributed under the Boost Software License, Version 1.0:
6 //
7 // Permission is hereby granted, free of charge, to any person or organization
8 // obtaining a copy of the software and accompanying documentation covered by
9 // this license (the "Software") to use, reproduce, display, distribute,
10 // execute, and transmit the Software, and to prepare derivative works of the
11 // Software, and to permit third-parties to whom the Software is furnished to
12 // do so, all subject to the following:
13 //
14 // The copyright notices in the Software and this entire statement, including
15 // the above license grant, this restriction and the following disclaimer,
16 // must be included in all copies of the Software, in whole or in part, and
17 // all derivative works of the Software, unless such copies or derivative
18 // works are solely in the form of machine-executable object code generated by
19 // a source language processor.
20 //
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 // FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
24 // SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
25 // FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
26 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 // DEALINGS IN THE SOFTWARE.
28 
29 #ifndef libpbe_charset_char_conv_hh
30 #define libpbe_charset_char_conv_hh
31 
32 #include "charset_t.hh"
33 #include "charset_traits.hh"
34 #include "error_policy.hh"
35 
36 #include <boost/static_assert.hpp>
37 
38 #include "compiler_magic.hh"
39 
40 
41 namespace pbe {
42 
43 // Conversion of characters between character sets
44 // -----------------------------------------------
45 //
46 // This file provides facilities to convert a single character from
47 // one character set to another.  It's implemented using specialisations
48 // for character set pairs in other files.
49 // A template parameter specifies a policy for error handling.
50 // Because function templates can't be partially specialised, and
51 // the character-set-pair specialisation will not want to be specialised
52 // on the error handling polocy, we need to wrap the conversion in a
53 // class.
54 // The default implementation here converts to a UCS4 character as an
55 // intermediate step, which will work as long as the necessary supporting
56 // conversions are implemented somehow.
57 // There's also a specialisation here for the null conversion where source
58 // and destination are the same.
59 
60 
61 // Base template, with default implementation via ucs4:
62 
63 template <charset_t from_cs, charset_t to_cs, typename error_policy>
64 struct char_conv {
65   // We shouldn't be here if from_cs or to_cs is ucs4; that indicates recursion.
66   // A specialisation should have been invoked.  Maybe the appropriate
67   // specialisation hasn't been #included, or hasn't been written?
68   BOOST_STATIC_ASSERT(from_cs!=cs::ucs4 && to_cs!=cs::ucs4);
69 
70   // FIXME shouldn't this be a static member function?
71   typename charset_traits<to_cs>::char_t
operator ()pbe::char_conv72   operator() ( typename charset_traits<from_cs>::char_t c,
73                typename charset_traits<from_cs>::state_t& from_state
74                  = charset_traits<from_cs>::state_t(),
75                typename charset_traits<to_cs>::state_t& to_state
76                  = charset_traits<to_cs>::state_t() )
77   {
78     charset_traits<cs::ucs4>::state_t ucs4_state;
79     char32_t tmp = char_conv<from_cs, cs::ucs4, error_policy>() (c,from_state,ucs4_state);
80     return         char_conv<cs::ucs4,   to_cs, error_policy>() (tmp,ucs4_state,to_state);
81   }
82 };
83 
84 
85 // Specialisation for trivial conversion to the same character set:
86 template <charset_t cset, typename error_policy>
87 struct char_conv<cset,cset,error_policy> {
88   typename charset_traits<cset>::char_t
operator ()pbe::char_conv89   operator() ( typename charset_traits<cset>::char_t c,
90                PBE_UNUSED_ARG(typename charset_traits<cset>::state_t& from_state)
91                  = charset_traits<cset>::state_t(),
92                PBE_UNUSED_ARG(typename charset_traits<cset>::state_t& to_state)
93                  = charset_traits<cset>::state_t() )
94   {
95     return c;
96   }
97 };
98 
99 
100 // This macro is used elsewhere to define trivial conversions.
101 
102 #define IDENTITY_CHAR_CONV(FROM_CS,TO_CS)                            \
103 template <typename error_policy>                                     \
104 struct char_conv<FROM_CS,TO_CS,error_policy> {                       \
105   charset_traits<TO_CS>::char_t                                      \
106   operator() ( charset_traits<FROM_CS>::char_t c,                    \
107                charset_traits<FROM_CS>::state_t&,                    \
108                charset_traits<TO_CS>::state_t& ) {                   \
109     return static_cast<unsigned charset_traits<FROM_CS>::char_t>(c); \
110   }                                                                  \
111 };
112 
113 
114 };
115 
116 #endif
117