1 // Copyright (c) 2001-2011 Hartmut Kaiser
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)
6 #if !defined(BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM)
7 #define BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM
9 #include <boost/spirit/home/support/common_terminals.hpp>
10 #include <boost/spirit/home/support/info.hpp>
11 #include <boost/spirit/home/support/unused.hpp>
12 #include <boost/spirit/home/support/attributes_fwd.hpp>
13 #include <boost/spirit/home/support/detail/get_encoding.hpp>
14 #include <boost/spirit/home/karma/detail/attributes.hpp>
15 #include <boost/spirit/home/karma/detail/extract_from.hpp>
16 #include <boost/spirit/home/karma/domain.hpp>
17 #include <boost/spirit/home/karma/meta_compiler.hpp>
18 #include <boost/spirit/home/karma/reference.hpp>
19 #include <boost/spirit/home/karma/generate.hpp>
20 #include <boost/spirit/home/karma/delimit_out.hpp>
21 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
22 #include <boost/spirit/home/karma/detail/string_generate.hpp>
23 #include <boost/config.hpp>
24 #include <boost/shared_ptr.hpp>
25 #include <boost/mpl/if.hpp>
29 #if defined(BOOST_MSVC)
30 # pragma warning(push)
31 # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning
34 ///////////////////////////////////////////////////////////////////////////////
35 namespace boost { namespace spirit { namespace traits
37 template <typename T, typename Attribute, typename Enable>
41 mpl::eval_if<fusion::traits::is_sequence<T>
42 , traits::detail::value_at_c<T, 0>
43 , detail::add_const_ref<T> > sequence_type;
45 mpl::eval_if<traits::is_container<T>
46 , traits::container_value<T>
47 , sequence_type>::type type;
50 template <typename T_>
51 static type call(T_ const& t, mpl::false_, mpl::true_)
53 return fusion::at_c<0>(t);
57 template <typename T_, typename IsSequence>
58 static type call(T_ const& t, mpl::true_, IsSequence)
63 // not a container and not a fusion sequence
64 template <typename T_>
65 static type call(T_ const& t, mpl::false_, mpl::false_)
70 static type call(T const& t)
72 typedef typename traits::is_container<T>::type is_container;
73 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
75 return call(t, is_container(), is_sequence());
79 template <typename Attribute>
80 struct symbols_lookup<Attribute, Attribute>
82 typedef Attribute const& type;
84 static type call(Attribute const& t)
90 template <typename Attribute, typename T, typename Enable>
94 mpl::eval_if<fusion::traits::is_sequence<T>
95 , traits::detail::value_at_c<T, 1>
96 , mpl::identity<unused_type> > sequence_type;
98 mpl::eval_if<traits::is_container<T>
99 , traits::container_value<T>
100 , sequence_type>::type type;
103 template <typename T_>
104 static type call(T_ const& t, mpl::false_, mpl::true_)
106 return fusion::at_c<1>(t);
110 template <typename T_, typename IsSequence>
111 static type call(T_ const& t, mpl::true_, IsSequence)
116 // not a container nor a fusion sequence
117 template <typename T_>
118 static type call(T_ const&, mpl::false_, mpl::false_)
123 static type call(T const& t)
125 typedef typename traits::is_container<T>::type is_container;
126 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
128 return call(t, is_container(), is_sequence());
132 template <typename Attribute>
133 struct symbols_value<Attribute, Attribute>
135 typedef unused_type type;
137 static type call(Attribute const&)
144 ///////////////////////////////////////////////////////////////////////////////
145 namespace boost { namespace spirit { namespace karma
147 ///////////////////////////////////////////////////////////////////////////
148 template <typename T, typename Attribute>
149 struct symbols_lookup
151 traits::not_is_unused<T>
152 , std::map<Attribute, T>
153 , std::set<Attribute>
157 ///////////////////////////////////////////////////////////////////////////
160 ///////////////////////////////////////////////////////////////////////
161 template <typename CharEncoding, typename Tag>
162 struct generate_encoded
165 proto::terminal<tag::char_code<Tag, CharEncoding> >::type
168 template <typename OutputIterator, typename Expr, typename Attribute>
169 static bool call(OutputIterator& sink, Expr const& expr
170 , Attribute const& attr)
172 encoding_type const encoding = encoding_type();
173 return karma::generate(sink, encoding[expr], attr);
178 struct generate_encoded<unused_type, unused_type>
180 template <typename OutputIterator, typename Expr, typename Attribute>
181 static bool call(OutputIterator& sink, Expr const& expr
182 , Attribute const& attr)
184 return karma::generate(sink, expr, attr);
190 typename Attribute = char, typename T = unused_type
191 , typename Lookup = typename symbols_lookup<T, Attribute>::type
192 , typename CharEncoding = unused_type, typename Tag = unused_type>
195 typename proto::terminal<
196 reference<symbols<Attribute, T, Lookup, CharEncoding, Tag> >
198 , symbols<Attribute, T, Lookup, CharEncoding, Tag> >
199 , primitive_generator<
200 symbols<Attribute, T, Lookup, CharEncoding, Tag> >
202 typedef T value_type; // the value associated with each entry
204 typedef reference<symbols> reference_;
205 typedef typename proto::terminal<reference_>::type terminal;
206 typedef proto::extends<terminal, symbols> base_type;
208 template <typename Context, typename Unused>
211 typedef Attribute type;
214 symbols(std::string const& name = "symbols")
215 : base_type(terminal::make(reference_(*this)))
218 , lookup(new Lookup())
222 symbols(symbols const& syms)
223 : base_type(terminal::make(reference_(*this)))
226 , lookup(syms.lookup)
230 template <typename CharEncoding_, typename Tag_>
231 symbols(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& syms)
232 : base_type(terminal::make(reference_(*this)))
235 , lookup(syms.lookup)
239 template <typename Symbols, typename Data>
240 symbols(Symbols const& syms, Data const& data
241 , std::string const& name = "symbols")
242 : base_type(terminal::make(reference_(*this)))
245 , lookup(new Lookup())
248 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
249 typename range_const_iterator<Data>::type di = boost::begin(data);
250 while (si != boost::end(syms))
255 operator=(symbols const& rhs)
257 *lookup = *rhs.lookup;
262 template <typename CharEncoding_, typename Tag_>
264 operator=(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& rhs)
266 *lookup = *rhs.lookup;
279 template <typename Attr, typename T_>
281 operator=(std::pair<Attr, T_> const& p)
284 return add(p.first, p.second);
287 template <typename Attr, typename T_>
289 operator+= (symbols& sym, std::pair<Attr, T_> const& p)
291 return sym.add(p.first, p.second);
294 template <typename Attr>
295 friend remover const&
296 operator-= (symbols& sym, Attr const& attr)
298 return sym.remove(attr);
301 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
302 // non-const version needed to suppress proto's += kicking in
303 template <typename Attr, typename T_>
305 operator+= (symbols& sym, std::pair<Attr, T_>& p)
307 return sym.add(p.first, p.second);
310 // non-const version needed to suppress proto's -= kicking in
311 template <typename Attr>
312 friend remover const&
313 operator-= (symbols& sym, Attr& attr)
315 return sym.remove(attr);
318 // for rvalue references
319 template <typename Attr, typename T_>
321 operator+= (symbols& sym, std::pair<Attr, T_>&& p)
323 return sym.add(p.first, p.second);
326 // for rvalue references
327 template <typename Attr>
328 friend remover const&
329 operator-= (symbols& sym, Attr&& attr)
331 return sym.remove(attr);
334 template <typename F>
335 void for_each(F f) const
337 std::for_each(lookup->begin(), lookup->end(), f);
340 template <typename Attr>
341 value_type* find(Attr const& attr)
343 typename Lookup::iterator it = lookup->find(attr);
344 return (it != lookup->end()) ? &(*it).second : 0;
347 template <typename Attr>
348 value_type& at(Attr const& attr)
350 return (*lookup)[attr];
353 ///////////////////////////////////////////////////////////////////////
354 template <typename OutputIterator, typename Context, typename Delimiter
356 bool generate(OutputIterator& sink, Context&, Delimiter const& d
357 , Attr const& attr) const
359 typename Lookup::iterator it = lookup->find(
360 traits::symbols_lookup<Attr, Attribute>::call(attr));
361 if (it == lookup->end())
364 return karma::detail::generate_encoded<CharEncoding, Tag>::call(
366 , traits::symbols_value<Attribute, Attr>::call(attr)) &&
367 karma::delimit_out(sink, d);
370 template <typename Context>
371 info what(Context&) const
376 void name(std::string const &str)
380 std::string const &name() const
385 ///////////////////////////////////////////////////////////////////////
388 template <typename, typename = unused_type>
389 struct result { typedef adder const& type; };
396 template <typename Attr>
398 operator()(Attr const& attr, T const& val = T()) const
400 sym.lookup->insert(typename Lookup::value_type(attr, val));
404 template <typename Attr>
406 operator, (Attr const& attr) const
408 sym.lookup->insert(typename Lookup::value_type(attr, T()));
415 // silence MSVC warning C4512: assignment operator could not be generated
416 adder& operator= (adder const&);
422 struct result { typedef remover const& type; };
424 remover(symbols& sym)
429 template <typename Attr>
431 operator()(Attr const& attr) const
433 sym.lookup->erase(attr);
437 template <typename Attr>
439 operator, (Attr const& attr) const
441 sym.lookup->erase(attr);
448 // silence MSVC warning C4512: assignment operator could not be generated
449 remover& operator= (remover const&);
454 shared_ptr<Lookup> lookup;
458 ///////////////////////////////////////////////////////////////////////////
459 // specialization for unused stored type
461 typename Attribute, typename Lookup
462 , typename CharEncoding, typename Tag>
463 struct symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
465 typename proto::terminal<
466 spirit::karma::reference<
467 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
469 , symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
471 , spirit::karma::generator<
472 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
474 typedef unused_type value_type; // the value associated with each entry
476 typedef spirit::karma::reference<symbols> reference_;
477 typedef typename proto::terminal<reference_>::type terminal;
478 typedef proto::extends<terminal, symbols> base_type;
480 template <typename Context, typename Unused>
483 typedef Attribute type;
486 symbols(std::string const& name = "symbols")
487 : base_type(terminal::make(reference_(*this)))
490 , lookup(new Lookup())
494 symbols(symbols const& syms)
495 : base_type(terminal::make(reference_(*this)))
498 , lookup(syms.lookup)
502 template <typename CharEncoding_, typename Tag_>
503 symbols(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& syms)
504 : base_type(terminal::make(reference_(*this)))
507 , lookup(syms.lookup)
511 template <typename Symbols, typename Data>
512 symbols(Symbols const& syms, Data const& data
513 , std::string const& name = "symbols")
514 : base_type(terminal::make(reference_(*this)))
517 , lookup(new Lookup())
520 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
521 typename range_const_iterator<Data>::type di = boost::begin(data);
522 while (si != boost::end(syms))
527 operator=(symbols const& rhs)
529 *lookup = *rhs.lookup;
534 template <typename CharEncoding_, typename Tag_>
536 operator=(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& rhs)
538 *lookup = *rhs.lookup;
551 template <typename Attr>
553 operator=(Attr const& attr)
559 template <typename Attr>
561 operator+= (symbols& sym, Attr const& attr)
563 return sym.add(attr);
566 template <typename Attr>
567 friend remover const&
568 operator-= (symbols& sym, Attr const& attr)
570 return sym.remove(attr);
573 // non-const version needed to suppress proto's += kicking in
574 template <typename Attr>
576 operator+= (symbols& sym, Attr& attr)
578 return sym.add(attr);
581 // non-const version needed to suppress proto's -= kicking in
582 template <typename Attr>
583 friend remover const&
584 operator-= (symbols& sym, Attr& attr)
586 return sym.remove(attr);
589 template <typename F>
590 void for_each(F f) const
592 std::for_each(lookup->begin(), lookup->end(), f);
595 template <typename Attr>
596 value_type const* find(Attr const& attr)
598 typename Lookup::iterator it = lookup->find(attr);
599 return (it != lookup->end()) ? &unused : 0;
602 template <typename Attr>
603 value_type at(Attr const& attr)
605 typename Lookup::iterator it = lookup->find(attr);
606 if (it == lookup->end())
611 ///////////////////////////////////////////////////////////////////////
612 template <typename OutputIterator, typename Context, typename Delimiter
614 bool generate(OutputIterator& sink, Context&, Delimiter const& d
615 , Attr const& attr) const
617 typename Lookup::iterator it = lookup->find(
618 traits::symbols_lookup<Attr, Attribute>::call(attr));
619 if (it == lookup->end())
622 return karma::detail::generate_encoded<CharEncoding, Tag>::
624 , traits::symbols_lookup<Attr, Attribute>::call(attr)
626 karma::delimit_out(sink, d);
629 template <typename Context>
630 info what(Context&) const
635 void name(std::string const &str)
639 std::string const &name() const
644 ///////////////////////////////////////////////////////////////////////
647 template <typename, typename = unused_type>
648 struct result { typedef adder const& type; };
655 template <typename Attr>
657 operator()(Attr const& attr) const
659 sym.lookup->insert(attr);
663 template <typename Attr>
665 operator, (Attr const& attr) const
667 sym.lookup->insert(attr);
674 // silence MSVC warning C4512: assignment operator could not be generated
675 adder& operator= (adder const&);
681 struct result { typedef remover const& type; };
683 remover(symbols& sym)
688 template <typename Attr>
690 operator()(Attr const& attr) const
692 sym.lookup->erase(attr);
696 template <typename Attr>
698 operator, (Attr const& attr) const
700 sym.lookup->erase(attr);
707 // silence MSVC warning C4512: assignment operator could not be generated
708 remover& operator= (remover const&);
713 shared_ptr<Lookup> lookup;
717 ///////////////////////////////////////////////////////////////////////////
718 // Generator generators: make_xxx function (objects)
719 ///////////////////////////////////////////////////////////////////////////
720 template <typename Attribute, typename T, typename Lookup
721 , typename CharEnconding, typename Tag, typename Modifiers>
722 struct make_primitive<
723 reference<symbols<Attribute, T, Lookup, CharEnconding, Tag> >
726 static bool const lower =
727 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
728 static bool const upper =
729 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
732 symbols<Attribute, T, Lookup, CharEnconding, Tag>
735 typedef typename mpl::if_c<
739 , typename spirit::detail::get_encoding_with_case<
740 Modifiers, unused_type, lower || upper>::type
741 , typename detail::get_casetag<Modifiers, lower || upper>::type>
745 result_type operator()(reference_ ref, unused_type) const
747 return result_type(ref.ref.get());
752 namespace boost { namespace spirit { namespace traits
754 ///////////////////////////////////////////////////////////////////////////
755 template <typename Attribute, typename T, typename Lookup
756 , typename CharEncoding, typename Tag
757 , typename Attr, typename Context, typename Iterator>
758 struct handles_container<karma::symbols<Attribute, T, Lookup, CharEncoding, Tag>
759 , Attr, Context, Iterator>
760 : traits::is_container<Attr> {};
763 #if defined(BOOST_MSVC)
764 # pragma warning(pop)