File indexing completed on 2025-01-19 09:47:39
0001
0002
0003
0004
0005
0006 #if !defined(BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM)
0007 #define BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM
0008
0009 #include <boost/spirit/home/support/common_terminals.hpp>
0010 #include <boost/spirit/home/support/info.hpp>
0011 #include <boost/spirit/home/support/unused.hpp>
0012 #include <boost/spirit/home/support/attributes_fwd.hpp>
0013 #include <boost/spirit/home/support/detail/get_encoding.hpp>
0014 #include <boost/spirit/home/karma/detail/attributes.hpp>
0015 #include <boost/spirit/home/karma/detail/extract_from.hpp>
0016 #include <boost/spirit/home/karma/domain.hpp>
0017 #include <boost/spirit/home/karma/meta_compiler.hpp>
0018 #include <boost/spirit/home/karma/reference.hpp>
0019 #include <boost/spirit/home/karma/generate.hpp>
0020 #include <boost/spirit/home/karma/delimit_out.hpp>
0021 #include <boost/spirit/home/karma/detail/get_casetag.hpp>
0022 #include <boost/spirit/home/karma/detail/string_generate.hpp>
0023 #include <boost/config.hpp>
0024 #include <boost/proto/extends.hpp>
0025 #include <boost/proto/traits.hpp>
0026 #include <boost/shared_ptr.hpp>
0027 #include <boost/mpl/if.hpp>
0028 #include <map>
0029 #include <set>
0030
0031 #if defined(BOOST_MSVC)
0032 # pragma warning(push)
0033 # pragma warning(disable: 4355)
0034 #endif
0035
0036
0037 namespace boost { namespace spirit { namespace traits
0038 {
0039 template <typename T, typename Attribute, typename Enable>
0040 struct symbols_lookup
0041 {
0042 typedef
0043 mpl::eval_if<fusion::traits::is_sequence<T>
0044 , traits::detail::value_at_c<T, 0>
0045 , detail::add_const_ref<T> > sequence_type;
0046 typedef typename
0047 mpl::eval_if<traits::is_container<T>
0048 , traits::container_value<T>
0049 , sequence_type>::type type;
0050
0051
0052 template <typename T_>
0053 static type call(T_ const& t, mpl::false_, mpl::true_)
0054 {
0055 return fusion::at_c<0>(t);
0056 }
0057
0058
0059 template <typename T_, typename IsSequence>
0060 static type call(T_ const& t, mpl::true_, IsSequence)
0061 {
0062 return t[0];
0063 }
0064
0065
0066 template <typename T_>
0067 static type call(T_ const& t, mpl::false_, mpl::false_)
0068 {
0069 return t;
0070 }
0071
0072 static type call(T const& t)
0073 {
0074 typedef typename traits::is_container<T>::type is_container;
0075 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
0076
0077 return call(t, is_container(), is_sequence());
0078 }
0079 };
0080
0081 template <typename Attribute>
0082 struct symbols_lookup<Attribute, Attribute>
0083 {
0084 typedef Attribute const& type;
0085
0086 static type call(Attribute const& t)
0087 {
0088 return t;
0089 }
0090 };
0091
0092 template <typename Attribute, typename T, typename Enable>
0093 struct symbols_value
0094 {
0095 typedef
0096 mpl::eval_if<fusion::traits::is_sequence<T>
0097 , traits::detail::value_at_c<T, 1>
0098 , mpl::identity<unused_type> > sequence_type;
0099 typedef typename
0100 mpl::eval_if<traits::is_container<T>
0101 , traits::container_value<T>
0102 , sequence_type>::type type;
0103
0104
0105 template <typename T_>
0106 static type call(T_ const& t, mpl::false_, mpl::true_)
0107 {
0108 return fusion::at_c<1>(t);
0109 }
0110
0111
0112 template <typename T_, typename IsSequence>
0113 static type call(T_ const& t, mpl::true_, IsSequence)
0114 {
0115 return t[1];
0116 }
0117
0118
0119 template <typename T_>
0120 static type call(T_ const&, mpl::false_, mpl::false_)
0121 {
0122 return unused;
0123 }
0124
0125 static type call(T const& t)
0126 {
0127 typedef typename traits::is_container<T>::type is_container;
0128 typedef typename fusion::traits::is_sequence<T>::type is_sequence;
0129
0130 return call(t, is_container(), is_sequence());
0131 }
0132 };
0133
0134 template <typename Attribute>
0135 struct symbols_value<Attribute, Attribute>
0136 {
0137 typedef unused_type type;
0138
0139 static type call(Attribute const&)
0140 {
0141 return unused;
0142 }
0143 };
0144 }}}
0145
0146
0147 namespace boost { namespace spirit { namespace karma
0148 {
0149
0150 template <typename T, typename Attribute>
0151 struct symbols_lookup
0152 : mpl::if_<
0153 traits::not_is_unused<T>
0154 , std::map<Attribute, T>
0155 , std::set<Attribute>
0156 >
0157 {};
0158
0159
0160 namespace detail
0161 {
0162
0163 template <typename CharEncoding, typename Tag>
0164 struct generate_encoded
0165 {
0166 typedef typename
0167 proto::terminal<tag::char_code<Tag, CharEncoding> >::type
0168 encoding_type;
0169
0170 template <typename OutputIterator, typename Expr, typename Attribute>
0171 static bool call(OutputIterator& sink, Expr const& expr
0172 , Attribute const& attr)
0173 {
0174 encoding_type const encoding = encoding_type();
0175 return karma::generate(sink, encoding[expr], attr);
0176 }
0177 };
0178
0179 template <>
0180 struct generate_encoded<unused_type, unused_type>
0181 {
0182 template <typename OutputIterator, typename Expr, typename Attribute>
0183 static bool call(OutputIterator& sink, Expr const& expr
0184 , Attribute const& attr)
0185 {
0186 return karma::generate(sink, expr, attr);
0187 }
0188 };
0189 }
0190
0191 template <
0192 typename Attribute = char, typename T = unused_type
0193 , typename Lookup = typename symbols_lookup<T, Attribute>::type
0194 , typename CharEncoding = unused_type, typename Tag = unused_type>
0195 struct symbols
0196 : proto::extends<
0197 typename proto::terminal<
0198 reference<symbols<Attribute, T, Lookup, CharEncoding, Tag> >
0199 >::type
0200 , symbols<Attribute, T, Lookup, CharEncoding, Tag> >
0201 , primitive_generator<
0202 symbols<Attribute, T, Lookup, CharEncoding, Tag> >
0203 {
0204 typedef T value_type;
0205
0206 typedef reference<symbols> reference_;
0207 typedef typename proto::terminal<reference_>::type terminal;
0208 typedef proto::extends<terminal, symbols> base_type;
0209
0210 template <typename Context, typename Unused>
0211 struct attribute
0212 {
0213 typedef Attribute type;
0214 };
0215
0216 symbols(std::string const& name = "symbols")
0217 : base_type(terminal::make(reference_(*this)))
0218 , add(*this)
0219 , remove(*this)
0220 , lookup(new Lookup())
0221 , name_(name)
0222 {}
0223
0224 symbols(symbols const& syms)
0225 : base_type(terminal::make(reference_(*this)))
0226 , add(*this)
0227 , remove(*this)
0228 , lookup(syms.lookup)
0229 , name_(syms.name_)
0230 {}
0231
0232 template <typename CharEncoding_, typename Tag_>
0233 symbols(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& syms)
0234 : base_type(terminal::make(reference_(*this)))
0235 , add(*this)
0236 , remove(*this)
0237 , lookup(syms.lookup)
0238 , name_(syms.name_)
0239 {}
0240
0241 template <typename Symbols, typename Data>
0242 symbols(Symbols const& syms, Data const& data
0243 , std::string const& name = "symbols")
0244 : base_type(terminal::make(reference_(*this)))
0245 , add(*this)
0246 , remove(*this)
0247 , lookup(new Lookup())
0248 , name_(name)
0249 {
0250 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
0251 typename range_const_iterator<Data>::type di = boost::begin(data);
0252 while (si != boost::end(syms))
0253 add(*si++, *di++);
0254 }
0255
0256 symbols&
0257 operator=(symbols const& rhs)
0258 {
0259 *lookup = *rhs.lookup;
0260 name_ = rhs.name_;
0261 return *this;
0262 }
0263
0264 template <typename CharEncoding_, typename Tag_>
0265 symbols&
0266 operator=(symbols<Attribute, T, Lookup, CharEncoding_, Tag_> const& rhs)
0267 {
0268 *lookup = *rhs.lookup;
0269 name_ = rhs.name_;
0270 return *this;
0271 }
0272
0273 void clear()
0274 {
0275 lookup->clear();
0276 }
0277
0278 struct adder;
0279 struct remover;
0280
0281 template <typename Attr, typename T_>
0282 adder const&
0283 operator=(std::pair<Attr, T_> const& p)
0284 {
0285 lookup->clear();
0286 return add(p.first, p.second);
0287 }
0288
0289 template <typename Attr, typename T_>
0290 friend adder const&
0291 operator+= (symbols& sym, std::pair<Attr, T_> const& p)
0292 {
0293 return sym.add(p.first, p.second);
0294 }
0295
0296 template <typename Attr>
0297 friend remover const&
0298 operator-= (symbols& sym, Attr const& attr)
0299 {
0300 return sym.remove(attr);
0301 }
0302
0303 #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES)
0304
0305 template <typename Attr, typename T_>
0306 friend adder const&
0307 operator+= (symbols& sym, std::pair<Attr, T_>& p)
0308 {
0309 return sym.add(p.first, p.second);
0310 }
0311
0312
0313 template <typename Attr>
0314 friend remover const&
0315 operator-= (symbols& sym, Attr& attr)
0316 {
0317 return sym.remove(attr);
0318 }
0319 #else
0320
0321 template <typename Attr, typename T_>
0322 friend adder const&
0323 operator+= (symbols& sym, std::pair<Attr, T_>&& p)
0324 {
0325 return sym.add(p.first, p.second);
0326 }
0327
0328
0329 template <typename Attr>
0330 friend remover const&
0331 operator-= (symbols& sym, Attr&& attr)
0332 {
0333 return sym.remove(attr);
0334 }
0335 #endif
0336 template <typename F>
0337 void for_each(F f) const
0338 {
0339 std::for_each(lookup->begin(), lookup->end(), f);
0340 }
0341
0342 template <typename Attr>
0343 value_type* find(Attr const& attr)
0344 {
0345 typename Lookup::iterator it = lookup->find(attr);
0346 return (it != lookup->end()) ? &(*it).second : 0;
0347 }
0348
0349 template <typename Attr>
0350 value_type& at(Attr const& attr)
0351 {
0352 return (*lookup)[attr];
0353 }
0354
0355
0356 template <typename OutputIterator, typename Context, typename Delimiter
0357 , typename Attr>
0358 bool generate(OutputIterator& sink, Context&, Delimiter const& d
0359 , Attr const& attr) const
0360 {
0361 typename Lookup::iterator it = lookup->find(
0362 traits::symbols_lookup<Attr, Attribute>::call(attr));
0363 if (it == lookup->end())
0364 return false;
0365
0366 return karma::detail::generate_encoded<CharEncoding, Tag>::call(
0367 sink, (*it).second
0368 , traits::symbols_value<Attribute, Attr>::call(attr)) &&
0369 karma::delimit_out(sink, d);
0370 }
0371
0372 template <typename Context>
0373 info what(Context&) const
0374 {
0375 return info(name_);
0376 }
0377
0378 void name(std::string const &str)
0379 {
0380 name_ = str;
0381 }
0382 std::string const &name() const
0383 {
0384 return name_;
0385 }
0386
0387
0388 #ifdef _MSC_VER
0389 # pragma warning(push)
0390 # pragma warning(disable: 4512)
0391 #endif
0392 struct adder
0393 {
0394 template <typename, typename = unused_type>
0395 struct result { typedef adder const& type; };
0396
0397 adder(symbols& sym)
0398 : sym(sym)
0399 {
0400 }
0401
0402 template <typename Attr>
0403 adder const&
0404 operator()(Attr const& attr, T const& val = T()) const
0405 {
0406 sym.lookup->insert(typename Lookup::value_type(attr, val));
0407 return *this;
0408 }
0409
0410 template <typename Attr>
0411 adder const&
0412 operator, (Attr const& attr) const
0413 {
0414 sym.lookup->insert(typename Lookup::value_type(attr, T()));
0415 return *this;
0416 }
0417
0418 symbols& sym;
0419 };
0420
0421 struct remover
0422 {
0423 template <typename>
0424 struct result { typedef remover const& type; };
0425
0426 remover(symbols& sym)
0427 : sym(sym)
0428 {
0429 }
0430
0431 template <typename Attr>
0432 remover const&
0433 operator()(Attr const& attr) const
0434 {
0435 sym.lookup->erase(attr);
0436 return *this;
0437 }
0438
0439 template <typename Attr>
0440 remover const&
0441 operator, (Attr const& attr) const
0442 {
0443 sym.lookup->erase(attr);
0444 return *this;
0445 }
0446
0447 symbols& sym;
0448 };
0449 #ifdef _MSC_VER
0450 # pragma warning(pop)
0451 #endif
0452
0453 adder add;
0454 remover remove;
0455 shared_ptr<Lookup> lookup;
0456 std::string name_;
0457 };
0458
0459
0460
0461 template <
0462 typename Attribute, typename Lookup
0463 , typename CharEncoding, typename Tag>
0464 struct symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
0465 : proto::extends<
0466 typename proto::terminal<
0467 spirit::karma::reference<
0468 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
0469 >::type
0470 , symbols<Attribute, unused_type, Lookup, CharEncoding, Tag>
0471 >
0472 , spirit::karma::generator<
0473 symbols<Attribute, unused_type, Lookup, CharEncoding, Tag> >
0474 {
0475 typedef unused_type value_type;
0476
0477 typedef spirit::karma::reference<symbols> reference_;
0478 typedef typename proto::terminal<reference_>::type terminal;
0479 typedef proto::extends<terminal, symbols> base_type;
0480
0481 template <typename Context, typename Unused>
0482 struct attribute
0483 {
0484 typedef Attribute type;
0485 };
0486
0487 symbols(std::string const& name = "symbols")
0488 : base_type(terminal::make(reference_(*this)))
0489 , add(*this)
0490 , remove(*this)
0491 , lookup(new Lookup())
0492 , name_(name)
0493 {}
0494
0495 symbols(symbols const& syms)
0496 : base_type(terminal::make(reference_(*this)))
0497 , add(*this)
0498 , remove(*this)
0499 , lookup(syms.lookup)
0500 , name_(syms.name_)
0501 {}
0502
0503 template <typename CharEncoding_, typename Tag_>
0504 symbols(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& syms)
0505 : base_type(terminal::make(reference_(*this)))
0506 , add(*this)
0507 , remove(*this)
0508 , lookup(syms.lookup)
0509 , name_(syms.name_)
0510 {}
0511
0512 template <typename Symbols, typename Data>
0513 symbols(Symbols const& syms, Data const& data
0514 , std::string const& name = "symbols")
0515 : base_type(terminal::make(reference_(*this)))
0516 , add(*this)
0517 , remove(*this)
0518 , lookup(new Lookup())
0519 , name_(name)
0520 {
0521 typename range_const_iterator<Symbols>::type si = boost::begin(syms);
0522 typename range_const_iterator<Data>::type di = boost::begin(data);
0523 while (si != boost::end(syms))
0524 add(*si++, *di++);
0525 }
0526
0527 symbols&
0528 operator=(symbols const& rhs)
0529 {
0530 *lookup = *rhs.lookup;
0531 name_ = rhs.name_;
0532 return *this;
0533 }
0534
0535 template <typename CharEncoding_, typename Tag_>
0536 symbols&
0537 operator=(symbols<Attribute, unused_type, Lookup, CharEncoding_, Tag_> const& rhs)
0538 {
0539 *lookup = *rhs.lookup;
0540 name_ = rhs.name_;
0541 return *this;
0542 }
0543
0544 void clear()
0545 {
0546 lookup->clear();
0547 }
0548
0549 struct adder;
0550 struct remover;
0551
0552 template <typename Attr>
0553 adder const&
0554 operator=(Attr const& attr)
0555 {
0556 lookup->clear();
0557 return add(attr);
0558 }
0559
0560 template <typename Attr>
0561 friend adder const&
0562 operator+= (symbols& sym, Attr const& attr)
0563 {
0564 return sym.add(attr);
0565 }
0566
0567 template <typename Attr>
0568 friend remover const&
0569 operator-= (symbols& sym, Attr const& attr)
0570 {
0571 return sym.remove(attr);
0572 }
0573
0574
0575 template <typename Attr>
0576 friend adder const&
0577 operator+= (symbols& sym, Attr& attr)
0578 {
0579 return sym.add(attr);
0580 }
0581
0582
0583 template <typename Attr>
0584 friend remover const&
0585 operator-= (symbols& sym, Attr& attr)
0586 {
0587 return sym.remove(attr);
0588 }
0589
0590 template <typename F>
0591 void for_each(F f) const
0592 {
0593 std::for_each(lookup->begin(), lookup->end(), f);
0594 }
0595
0596 template <typename Attr>
0597 value_type const* find(Attr const& attr)
0598 {
0599 typename Lookup::iterator it = lookup->find(attr);
0600 return (it != lookup->end()) ? &unused : 0;
0601 }
0602
0603 template <typename Attr>
0604 value_type at(Attr const& attr)
0605 {
0606 typename Lookup::iterator it = lookup->find(attr);
0607 if (it == lookup->end())
0608 add(attr);
0609 return unused;
0610 }
0611
0612
0613 template <typename OutputIterator, typename Context, typename Delimiter
0614 , typename Attr>
0615 bool generate(OutputIterator& sink, Context&, Delimiter const& d
0616 , Attr const& attr) const
0617 {
0618 typename Lookup::iterator it = lookup->find(
0619 traits::symbols_lookup<Attr, Attribute>::call(attr));
0620 if (it == lookup->end())
0621 return false;
0622
0623 return karma::detail::generate_encoded<CharEncoding, Tag>::
0624 call(sink
0625 , traits::symbols_lookup<Attr, Attribute>::call(attr)
0626 , unused) &&
0627 karma::delimit_out(sink, d);
0628 }
0629
0630 template <typename Context>
0631 info what(Context&) const
0632 {
0633 return info(name_);
0634 }
0635
0636 void name(std::string const &str)
0637 {
0638 name_ = str;
0639 }
0640 std::string const &name() const
0641 {
0642 return name_;
0643 }
0644
0645
0646 #ifdef _MSC_VER
0647 # pragma warning(push)
0648 # pragma warning(disable: 4512)
0649 #endif
0650 struct adder
0651 {
0652 template <typename, typename = unused_type>
0653 struct result { typedef adder const& type; };
0654
0655 adder(symbols& sym)
0656 : sym(sym)
0657 {
0658 }
0659
0660 template <typename Attr>
0661 adder const&
0662 operator()(Attr const& attr) const
0663 {
0664 sym.lookup->insert(attr);
0665 return *this;
0666 }
0667
0668 template <typename Attr>
0669 adder const&
0670 operator, (Attr const& attr) const
0671 {
0672 sym.lookup->insert(attr);
0673 return *this;
0674 }
0675
0676 symbols& sym;
0677 };
0678
0679 struct remover
0680 {
0681 template <typename>
0682 struct result { typedef remover const& type; };
0683
0684 remover(symbols& sym)
0685 : sym(sym)
0686 {
0687 }
0688
0689 template <typename Attr>
0690 remover const&
0691 operator()(Attr const& attr) const
0692 {
0693 sym.lookup->erase(attr);
0694 return *this;
0695 }
0696
0697 template <typename Attr>
0698 remover const&
0699 operator, (Attr const& attr) const
0700 {
0701 sym.lookup->erase(attr);
0702 return *this;
0703 }
0704
0705 symbols& sym;
0706 };
0707 #ifdef _MSC_VER
0708 # pragma warning(pop)
0709 #endif
0710
0711 adder add;
0712 remover remove;
0713 shared_ptr<Lookup> lookup;
0714 std::string name_;
0715 };
0716
0717
0718
0719
0720 template <typename Attribute, typename T, typename Lookup
0721 , typename CharEnconding, typename Tag, typename Modifiers>
0722 struct make_primitive<
0723 reference<symbols<Attribute, T, Lookup, CharEnconding, Tag> >
0724 , Modifiers>
0725 {
0726 static bool const lower =
0727 has_modifier<Modifiers, tag::char_code_base<tag::lower> >::value;
0728 static bool const upper =
0729 has_modifier<Modifiers, tag::char_code_base<tag::upper> >::value;
0730
0731 typedef reference<
0732 symbols<Attribute, T, Lookup, CharEnconding, Tag>
0733 > reference_;
0734
0735 typedef typename mpl::if_c<
0736 lower || upper
0737 , symbols<
0738 Attribute, T, Lookup
0739 , typename spirit::detail::get_encoding_with_case<
0740 Modifiers, unused_type, lower || upper>::type
0741 , typename detail::get_casetag<Modifiers, lower || upper>::type>
0742 , reference_>::type
0743 result_type;
0744
0745 result_type operator()(reference_ ref, unused_type) const
0746 {
0747 return result_type(ref.ref.get());
0748 }
0749 };
0750 }}}
0751
0752 namespace boost { namespace spirit { namespace traits
0753 {
0754
0755 template <typename Attribute, typename T, typename Lookup
0756 , typename CharEncoding, typename Tag
0757 , typename Attr, typename Context, typename Iterator>
0758 struct handles_container<karma::symbols<Attribute, T, Lookup, CharEncoding, Tag>
0759 , Attr, Context, Iterator>
0760 : traits::is_container<Attr> {};
0761 }}}
0762
0763 #if defined(BOOST_MSVC)
0764 # pragma warning(pop)
0765 #endif
0766
0767 #endif
0768