Imported Upstream version 1.72.0
[platform/upstream/boost.git] / boost / spirit / home / x3 / char / detail / cast_char.hpp
1 /*=============================================================================
2     Copyright (c) 2001-2014 Joel de Guzman
3     Copyright (c) 2001-2011 Hartmut Kaiser
4
5     Distributed under the Boost Software License, Version 1.0. (See accompanying
6     file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 =============================================================================*/
8 #if !defined(BOOST_SPIRIT_X3_CAST_CHAR_NOVEMBER_10_2006_0907AM)
9 #define BOOST_SPIRIT_X3_CAST_CHAR_NOVEMBER_10_2006_0907AM
10
11 #include <boost/type_traits/is_signed.hpp>
12 #include <boost/type_traits/make_unsigned.hpp>
13 #include <boost/type_traits/make_signed.hpp>
14
15 namespace boost { namespace spirit { namespace x3 { namespace detail
16 {
17     // Here's the thing... typical encodings (except ASCII) deal with unsigned
18     // integers > 127 (ASCII uses only 127). Yet, most char and wchar_t are signed.
19     // Thus, a char with value > 127 is negative (e.g. char 233 is -23). When you
20     // cast this to an unsigned int with 32 bits, you get 4294967273!
21     //
22     // The trick is to cast to an unsigned version of the source char first
23     // before casting to the target. {P.S. Don't worry about the code, the
24     // optimizer will optimize the if-else branches}
25
26     template <typename TargetChar, typename SourceChar>
27     TargetChar cast_char(SourceChar ch)
28     {
29 #if defined(_MSC_VER)
30 # pragma warning(push)
31 # pragma warning(disable: 4127) // conditional expression is constant
32 #endif
33         if (is_signed<TargetChar>::value != is_signed<SourceChar>::value)
34         {
35             if (is_signed<SourceChar>::value)
36             {
37                  // source is signed, target is unsigned
38                 typedef typename make_unsigned<SourceChar>::type USourceChar;
39                 return TargetChar(USourceChar(ch));
40             }
41             else
42             {
43                  // source is unsigned, target is signed
44                 typedef typename make_signed<SourceChar>::type SSourceChar;
45                 return TargetChar(SSourceChar(ch));
46             }
47         }
48         else
49         {
50             // source and target has same signedness
51             return TargetChar(ch); // just cast
52         }
53 #if defined(_MSC_VER)
54 # pragma warning(pop)
55 #endif
56     }
57 }}}}
58
59 #endif
60
61