PageRenderTime 43ms CodeModel.GetById 18ms app.highlight 22ms RepoModel.GetById 1ms app.codeStats 0ms

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