/Src/Dependencies/Boost/boost/spirit/home/qi/detail/assign_to.hpp

http://hadesmem.googlecode.com/ · C++ Header · 363 lines · 289 code · 42 blank · 32 comment · 13 complexity · a0283042a173649583e93dbaed3147a2 MD5 · raw file

  1. /*=============================================================================
  2. Copyright (c) 2001-2011 Joel de Guzman
  3. Copyright (c) 2001-2011 Hartmut Kaiser
  4. http://spirit.sourceforge.net/
  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_ASSIGN_TO_APR_16_2006_0812PM)
  9. #define BOOST_SPIRIT_ASSIGN_TO_APR_16_2006_0812PM
  10. #if defined(_MSC_VER)
  11. #pragma once
  12. #endif
  13. #include <boost/spirit/home/qi/detail/construct.hpp>
  14. #include <boost/spirit/home/support/unused.hpp>
  15. #include <boost/spirit/home/qi/detail/attributes.hpp>
  16. #include <boost/spirit/home/support/container.hpp>
  17. #include <boost/fusion/include/copy.hpp>
  18. #include <boost/ref.hpp>
  19. #include <boost/range/iterator_range.hpp>
  20. namespace boost { namespace spirit { namespace traits
  21. {
  22. ///////////////////////////////////////////////////////////////////////////
  23. // This file contains assignment utilities. The utilities provided also
  24. // accept spirit's unused_type; all no-ops. Compiler optimization will
  25. // easily strip these away.
  26. ///////////////////////////////////////////////////////////////////////////
  27. template <typename Attribute, typename Iterator, typename Enable>
  28. struct assign_to_attribute_from_iterators
  29. {
  30. static void
  31. call(Iterator const& first, Iterator const& last, Attribute& attr)
  32. {
  33. if (traits::is_empty(attr))
  34. attr = Attribute(first, last);
  35. else {
  36. for (Iterator i = first; i != last; ++i)
  37. push_back(attr, *i);
  38. }
  39. }
  40. };
  41. template <typename Attribute, typename Iterator>
  42. struct assign_to_attribute_from_iterators<
  43. reference_wrapper<Attribute>, Iterator>
  44. {
  45. static void
  46. call(Iterator const& first, Iterator const& last
  47. , reference_wrapper<Attribute> attr)
  48. {
  49. if (traits::is_empty(attr))
  50. attr = Attribute(first, last);
  51. else {
  52. for (Iterator i = first; i != last; ++i)
  53. push_back(attr, *i);
  54. }
  55. }
  56. };
  57. template <typename Attribute, typename Iterator>
  58. struct assign_to_attribute_from_iterators<
  59. boost::optional<Attribute>, Iterator>
  60. {
  61. static void
  62. call(Iterator const& first, Iterator const& last
  63. , boost::optional<Attribute>& attr)
  64. {
  65. Attribute val;
  66. assign_to(first, last, val);
  67. attr = val;
  68. }
  69. };
  70. template <typename Iterator>
  71. struct assign_to_attribute_from_iterators<
  72. iterator_range<Iterator>, Iterator>
  73. {
  74. static void
  75. call(Iterator const& first, Iterator const& last
  76. , iterator_range<Iterator>& attr)
  77. {
  78. attr = iterator_range<Iterator>(first, last);
  79. }
  80. };
  81. template <typename Iterator, typename Attribute>
  82. inline void
  83. assign_to(Iterator const& first, Iterator const& last, Attribute& attr)
  84. {
  85. assign_to_attribute_from_iterators<Attribute, Iterator>::
  86. call(first, last, attr);
  87. }
  88. template <typename Iterator>
  89. inline void
  90. assign_to(Iterator const&, Iterator const&, unused_type)
  91. {
  92. }
  93. ///////////////////////////////////////////////////////////////////////////
  94. template <typename T, typename Attribute>
  95. void assign_to(T const& val, Attribute& attr);
  96. template <typename Attribute, typename T, typename Enable>
  97. struct assign_to_attribute_from_value
  98. {
  99. typedef typename traits::one_element_sequence<Attribute>::type
  100. is_one_element_sequence;
  101. typedef typename mpl::eval_if<
  102. is_one_element_sequence
  103. , fusion::result_of::at_c<Attribute, 0>
  104. , mpl::identity<Attribute&>
  105. >::type type;
  106. template <typename T_>
  107. static void
  108. call(T_ const& val, Attribute& attr, mpl::false_)
  109. {
  110. attr = static_cast<Attribute>(val);
  111. }
  112. // This handles the case where the attribute is a single element fusion
  113. // sequence. We silently assign to the only element and treat it as the
  114. // attribute to parse the results into.
  115. template <typename T_>
  116. static void
  117. call(T_ const& val, Attribute& attr, mpl::true_)
  118. {
  119. typedef typename fusion::result_of::value_at_c<Attribute, 0>::type
  120. element_type;
  121. fusion::at_c<0>(attr) = static_cast<element_type>(val);
  122. }
  123. static void
  124. call(T const& val, Attribute& attr)
  125. {
  126. call(val, attr, is_one_element_sequence());
  127. }
  128. };
  129. template <typename Attribute>
  130. struct assign_to_attribute_from_value<Attribute, Attribute>
  131. {
  132. static void
  133. call(Attribute const& val, Attribute& attr)
  134. {
  135. attr = val;
  136. }
  137. };
  138. template <typename Attribute, typename T>
  139. struct assign_to_attribute_from_value<Attribute, reference_wrapper<T>
  140. , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
  141. {
  142. static void
  143. call(reference_wrapper<T> const& val, Attribute& attr)
  144. {
  145. assign_to(val.get(), attr);
  146. }
  147. };
  148. template <typename Attribute, typename T>
  149. struct assign_to_attribute_from_value<Attribute, boost::optional<T>
  150. , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
  151. {
  152. static void
  153. call(boost::optional<T> const& val, Attribute& attr)
  154. {
  155. assign_to(val.get(), attr);
  156. }
  157. };
  158. namespace detail
  159. {
  160. template <typename A, typename B>
  161. struct is_same_size_sequence
  162. : mpl::bool_<fusion::result_of::size<A>::value
  163. == fusion::result_of::size<B>::value>
  164. {};
  165. }
  166. template <typename Attribute, typename T>
  167. struct assign_to_attribute_from_value<Attribute, T,
  168. mpl::and_<
  169. fusion::traits::is_sequence<Attribute>,
  170. fusion::traits::is_sequence<T>,
  171. detail::is_same_size_sequence<Attribute, T>
  172. >
  173. >
  174. {
  175. static void
  176. call(T const& val, Attribute& attr)
  177. {
  178. fusion::copy(val, attr);
  179. }
  180. };
  181. ///////////////////////////////////////////////////////////////////////////
  182. template <typename Attribute, typename T, typename Enable>
  183. struct assign_to_container_from_value
  184. {
  185. // T is not a container and not a string
  186. template <typename T_>
  187. static void call(T_ const& val, Attribute& attr, mpl::false_, mpl::false_)
  188. {
  189. traits::push_back(attr, val);
  190. }
  191. // T is a container (but not a string), and T is convertible to the
  192. // value_type of the Attribute container
  193. template <typename T_>
  194. static void
  195. append_to_container_not_string(T_ const& val, Attribute& attr, mpl::true_)
  196. {
  197. traits::push_back(attr, val);
  198. }
  199. // T is a container (but not a string), generic overload
  200. template <typename T_>
  201. static void
  202. append_to_container_not_string(T_ const& val, Attribute& attr, mpl::false_)
  203. {
  204. typedef typename traits::container_iterator<T_ const>::type
  205. iterator_type;
  206. iterator_type end = traits::end(val);
  207. for (iterator_type i = traits::begin(val); i != end; traits::next(i))
  208. traits::push_back(attr, traits::deref(i));
  209. }
  210. // T is a container (but not a string)
  211. template <typename T_>
  212. static void call(T_ const& val, Attribute& attr, mpl::true_, mpl::false_)
  213. {
  214. typedef typename container_value<Attribute>::type value_type;
  215. typedef typename is_convertible<T, value_type>::type is_value_type;
  216. append_to_container_not_string(val, attr, is_value_type());
  217. }
  218. ///////////////////////////////////////////////////////////////////////
  219. // T is a string
  220. template <typename Iterator>
  221. static void append_to_string(Attribute& attr, Iterator begin, Iterator end)
  222. {
  223. for (Iterator i = begin; i != end; ++i)
  224. traits::push_back(attr, *i);
  225. }
  226. // T is string, but not convertible to value_type of container
  227. template <typename T_>
  228. static void append_to_container(T_ const& val, Attribute& attr, mpl::false_)
  229. {
  230. typedef typename char_type_of<T_>::type char_type;
  231. append_to_string(attr, traits::get_begin<char_type>(val)
  232. , traits::get_end<char_type>(val));
  233. }
  234. // T is string, and convertible to value_type of container
  235. template <typename T_>
  236. static void append_to_container(T_ const& val, Attribute& attr, mpl::true_)
  237. {
  238. traits::push_back(attr, val);
  239. }
  240. template <typename T_, typename Pred>
  241. static void call(T_ const& val, Attribute& attr, Pred, mpl::true_)
  242. {
  243. typedef typename container_value<Attribute>::type value_type;
  244. typedef typename is_convertible<T, value_type>::type is_value_type;
  245. append_to_container(val, attr, is_value_type());
  246. }
  247. ///////////////////////////////////////////////////////////////////////
  248. static void call(T const& val, Attribute& attr)
  249. {
  250. typedef typename traits::is_container<T>::type is_container;
  251. typedef typename traits::is_string<T>::type is_string;
  252. call(val, attr, is_container(), is_string());
  253. }
  254. };
  255. template <typename Attribute>
  256. struct assign_to_container_from_value<Attribute, Attribute>
  257. {
  258. static void
  259. call(Attribute const& val, Attribute& attr)
  260. {
  261. attr = val;
  262. }
  263. };
  264. template <typename Attribute, typename T>
  265. struct assign_to_container_from_value<Attribute, boost::optional<T>
  266. , typename disable_if<is_same<Attribute, boost::optional<T> > >::type>
  267. {
  268. static void
  269. call(boost::optional<T> const& val, Attribute& attr)
  270. {
  271. assign_to(val.get(), attr);
  272. }
  273. };
  274. template <typename Attribute, typename T>
  275. struct assign_to_container_from_value<Attribute, reference_wrapper<T>
  276. , typename disable_if<is_same<Attribute, reference_wrapper<T> > >::type>
  277. {
  278. static void
  279. call(reference_wrapper<T> const& val, Attribute& attr)
  280. {
  281. assign_to(val.get(), attr);
  282. }
  283. };
  284. ///////////////////////////////////////////////////////////////////////////
  285. namespace detail
  286. {
  287. // overload for non-container attributes
  288. template <typename T, typename Attribute>
  289. inline void
  290. assign_to(T const& val, Attribute& attr, mpl::false_)
  291. {
  292. assign_to_attribute_from_value<Attribute, T>::call(val, attr);
  293. }
  294. // overload for containers (but not for variants or optionals
  295. // holding containers)
  296. template <typename T, typename Attribute>
  297. inline void
  298. assign_to(T const& val, Attribute& attr, mpl::true_)
  299. {
  300. assign_to_container_from_value<Attribute, T>::call(val, attr);
  301. }
  302. }
  303. template <typename T, typename Attribute>
  304. inline void
  305. assign_to(T const& val, Attribute& attr)
  306. {
  307. typedef typename mpl::and_<
  308. traits::is_container<Attribute>
  309. , traits::not_is_variant<Attribute>
  310. , traits::not_is_optional<Attribute>
  311. >::type is_not_wrapped_container;
  312. detail::assign_to(val, attr, is_not_wrapped_container());
  313. }
  314. template <typename T>
  315. inline void
  316. assign_to(T const&, unused_type)
  317. {
  318. }
  319. }}}
  320. #endif