1 // Copyright (c) 2001-2011 Hartmut Kaiser 2 // 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 #if !defined(BOOST_SPIRIT_KARMA_META_CREATE_NOV_21_2009_0425PM) 7 #define BOOST_SPIRIT_KARMA_META_CREATE_NOV_21_2009_0425PM 8 9 #if defined(_MSC_VER) 10 #pragma once 11 #endif 12 13 #include <boost/spirit/home/karma/domain.hpp> 14 #include <boost/spirit/home/support/common_terminals.hpp> 15 #include <boost/spirit/home/support/auto/meta_create.hpp> 16 17 #include <boost/utility/enable_if.hpp> 18 #include <boost/variant.hpp> 19 #include <boost/optional.hpp> 20 #include <boost/config.hpp> 21 #include <boost/mpl/not.hpp> 22 #include <boost/mpl/fold.hpp> 23 #include <boost/mpl/vector.hpp> 24 #include <boost/mpl/push_back.hpp> 25 #include <boost/fusion/include/as_vector.hpp> 26 #include <boost/proto/tags.hpp> 27 #include <boost/type_traits/is_same.hpp> 28 29 /////////////////////////////////////////////////////////////////////////////// 30 namespace boost { namespace spirit { namespace karma 31 { 32 /////////////////////////////////////////////////////////////////////////// 33 // compatible STL containers 34 template <typename Container> 35 struct meta_create_container 36 { 37 typedef make_unary_proto_expr< 38 typename Container::value_type 39 , proto::tag::dereference, karma::domain 40 > make_proto_expr; 41 42 typedef typename make_proto_expr::type type; 43 callboost::spirit::karma::meta_create_container44 static type call() 45 { 46 return make_proto_expr::call(); 47 } 48 }; 49 50 /////////////////////////////////////////////////////////////////////////// 51 // String types 52 template <typename String> 53 struct meta_create_string 54 { 55 typedef spirit::standard::string_type type; callboost::spirit::karma::meta_create_string56 static type const call() { return type(); } 57 }; 58 59 template <> 60 struct meta_create_string<wchar_t*> 61 { 62 typedef spirit::standard_wide::string_type type; callboost::spirit::karma::meta_create_string63 static type const call() { return type(); } 64 }; 65 66 template <> 67 struct meta_create_string<wchar_t const*> 68 { 69 typedef spirit::standard_wide::string_type type; callboost::spirit::karma::meta_create_string70 static type const call() { return type(); } 71 }; 72 73 template <int N> 74 struct meta_create_string<wchar_t[N]> 75 { 76 typedef spirit::standard_wide::string_type type; callboost::spirit::karma::meta_create_string77 static type const call() { return type(); } 78 }; 79 80 template <int N> 81 struct meta_create_string<wchar_t const[N]> 82 { 83 typedef spirit::standard_wide::string_type type; callboost::spirit::karma::meta_create_string84 static type const call() { return type(); } 85 }; 86 87 template <int N> 88 struct meta_create_string<wchar_t(&)[N]> 89 { 90 typedef spirit::standard_wide::string_type type; callboost::spirit::karma::meta_create_string91 static type const call() { return type(); } 92 }; 93 94 template <int N> 95 struct meta_create_string<wchar_t const(&)[N]> 96 { 97 typedef spirit::standard_wide::string_type type; callboost::spirit::karma::meta_create_string98 static type const call() { return type(); } 99 }; 100 101 template <typename Traits, typename Allocator> 102 struct meta_create_string<std::basic_string<wchar_t, Traits, Allocator> > 103 { 104 typedef spirit::standard_wide::string_type type; callboost::spirit::karma::meta_create_string105 static type const call() { return type(); } 106 }; 107 108 /////////////////////////////////////////////////////////////////////////// 109 // Fusion sequences 110 template <typename Sequence> 111 struct meta_create_sequence 112 { 113 // create a mpl sequence from the given fusion sequence 114 typedef typename mpl::fold< 115 typename fusion::result_of::as_vector<Sequence>::type 116 , mpl::vector<>, mpl::push_back<mpl::_, mpl::_> 117 >::type sequence_type; 118 119 typedef make_nary_proto_expr< 120 sequence_type, proto::tag::shift_left, karma::domain 121 > make_proto_expr; 122 123 typedef typename make_proto_expr::type type; 124 callboost::spirit::karma::meta_create_sequence125 static type call() 126 { 127 return make_proto_expr::call(); 128 } 129 }; 130 131 /////////////////////////////////////////////////////////////////////////// 132 // the default is to use the standard streaming operator unless it's a 133 // STL container or a fusion sequence 134 135 // The default implementation will be chosen if no predefined mapping of 136 // the data type T to a Karma component is defined. 137 struct no_auto_mapping_exists {}; 138 139 template <typename T, typename Enable = void> 140 struct meta_create_impl : mpl::identity<no_auto_mapping_exists> {}; 141 142 template <typename T> 143 struct meta_create_impl<T 144 , typename enable_if< 145 mpl::and_< 146 traits::is_container<T> 147 , mpl::not_<traits::is_string<T> > 148 , mpl::not_<fusion::traits::is_sequence<T> > 149 > >::type> 150 : meta_create_container<T> {}; 151 152 template <typename T> 153 struct meta_create_impl<T 154 , typename enable_if<traits::is_string<T> >::type> 155 : meta_create_string<T> {}; 156 157 template <typename T> 158 struct meta_create_impl<T, typename enable_if< 159 spirit::detail::is_fusion_sequence_but_not_proto_expr<T> 160 >::type> 161 : meta_create_sequence<T> {}; 162 163 template <typename T, typename Enable = void> 164 struct meta_create : meta_create_impl<T> {}; 165 166 /////////////////////////////////////////////////////////////////////////// 167 // optional 168 template <typename T> 169 struct meta_create<boost::optional<T> > 170 { 171 typedef make_unary_proto_expr< 172 T, proto::tag::negate, karma::domain 173 > make_proto_expr; 174 175 typedef typename make_proto_expr::type type; 176 callboost::spirit::karma::meta_create177 static type call() 178 { 179 return make_proto_expr::call(); 180 } 181 }; 182 183 /////////////////////////////////////////////////////////////////////////// 184 // alternatives 185 template <BOOST_VARIANT_ENUM_PARAMS(typename T)> 186 struct meta_create<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> > 187 { 188 typedef make_nary_proto_expr< 189 typename boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>::types 190 , proto::tag::bitwise_or, karma::domain 191 > make_proto_expr; 192 193 typedef typename make_proto_expr::type type; 194 callboost::spirit::karma::meta_create195 static type call() 196 { 197 return make_proto_expr::call(); 198 } 199 }; 200 201 /////////////////////////////////////////////////////////////////////////// 202 // predefined specializations for primitive components 203 204 // character generator 205 template <> 206 struct meta_create<char> 207 { 208 typedef spirit::standard::char_type type; callboost::spirit::karma::meta_create209 static type const call() { return type(); } 210 }; 211 template <> 212 struct meta_create<signed char> 213 { 214 typedef spirit::standard::char_type type; callboost::spirit::karma::meta_create215 static type const call() { return type(); } 216 }; 217 template <> 218 struct meta_create<wchar_t> 219 { 220 typedef spirit::standard_wide::char_type type; callboost::spirit::karma::meta_create221 static type const call() { return type(); } 222 }; 223 224 template <> 225 struct meta_create<unsigned char> 226 { 227 typedef spirit::standard::char_type type; callboost::spirit::karma::meta_create228 static type const call() { return type(); } 229 }; 230 231 // boolean generator 232 template <> 233 struct meta_create<bool> 234 { 235 typedef spirit::bool_type type; callboost::spirit::karma::meta_create236 static type call() { return type(); } 237 }; 238 239 // integral generators 240 template <> 241 struct meta_create<int> 242 { 243 typedef spirit::int_type type; callboost::spirit::karma::meta_create244 static type call() { return type(); } 245 }; 246 template <> 247 struct meta_create<short> 248 { 249 typedef spirit::short_type type; callboost::spirit::karma::meta_create250 static type call() { return type(); } 251 }; 252 template <> 253 struct meta_create<long> 254 { 255 typedef spirit::long_type type; callboost::spirit::karma::meta_create256 static type call() { return type(); } 257 }; 258 template <> 259 struct meta_create<unsigned int> 260 { 261 typedef spirit::uint_type type; callboost::spirit::karma::meta_create262 static type call() { return type(); } 263 }; 264 #if !defined(BOOST_NO_INTRINSIC_WCHAR_T) 265 template <> 266 struct meta_create<unsigned short> 267 { 268 typedef spirit::ushort_type type; callboost::spirit::karma::meta_create269 static type call() { return type(); } 270 }; 271 #endif 272 template <> 273 struct meta_create<unsigned long> 274 { 275 typedef spirit::ulong_type type; callboost::spirit::karma::meta_create276 static type call() { return type(); } 277 }; 278 279 #ifdef BOOST_HAS_LONG_LONG 280 template <> 281 struct meta_create<boost::long_long_type> 282 { 283 typedef spirit::long_long_type type; callboost::spirit::karma::meta_create284 static type call() { return type(); } 285 }; 286 template <> 287 struct meta_create<boost::ulong_long_type> 288 { 289 typedef spirit::ulong_long_type type; callboost::spirit::karma::meta_create290 static type call() { return type(); } 291 }; 292 #endif 293 294 // floating point generators 295 template <> 296 struct meta_create<float> 297 { 298 typedef spirit::float_type type; callboost::spirit::karma::meta_create299 static type call() { return type(); } 300 }; 301 template <> 302 struct meta_create<double> 303 { 304 typedef spirit::double_type type; callboost::spirit::karma::meta_create305 static type call() { return type(); } 306 }; 307 template <> 308 struct meta_create<long double> 309 { 310 typedef spirit::long_double_type type; callboost::spirit::karma::meta_create311 static type call() { return type(); } 312 }; 313 }}} 314 315 /////////////////////////////////////////////////////////////////////////////// 316 namespace boost { namespace spirit { namespace traits 317 { 318 /////////////////////////////////////////////////////////////////////////// 319 // main customization point for create_generator 320 template <typename T, typename Enable = void> 321 struct create_generator : karma::meta_create<T> {}; 322 323 /////////////////////////////////////////////////////////////////////////// 324 // dispatch this to the karma related specializations 325 template <typename T> 326 struct meta_create<karma::domain, T> 327 : create_generator<typename spirit::detail::remove_const_ref<T>::type> {}; 328 329 /////////////////////////////////////////////////////////////////////////// 330 // Check whether a valid mapping exits for the given data type to a Karma 331 // component 332 template <typename T> 333 struct meta_create_exists<karma::domain, T> 334 : mpl::not_<is_same< 335 karma::no_auto_mapping_exists 336 , typename meta_create<karma::domain, T>::type 337 > > {}; 338 }}} 339 340 #endif 341