Chris@16: // Copyright (c) 2001-2011 Hartmut Kaiser Chris@16: // Chris@16: // Distributed under the Boost Software License, Version 1.0. (See accompanying Chris@16: // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) Chris@16: Chris@16: #if !defined(BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM) Chris@16: #define BOOST_SPIRIT_KARMA_SYMBOLS_NOV_23_2009_1251PM Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: #if defined(BOOST_MSVC) Chris@16: # pragma warning(push) Chris@16: # pragma warning(disable: 4355) // 'this' : used in base member initializer list warning Chris@16: #endif Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit { namespace traits Chris@16: { Chris@16: template Chris@16: struct symbols_lookup Chris@16: { Chris@16: typedef Chris@16: mpl::eval_if Chris@16: , traits::detail::value_at_c Chris@16: , detail::add_const_ref > sequence_type; Chris@16: typedef typename Chris@16: mpl::eval_if Chris@16: , traits::container_value Chris@16: , sequence_type>::type type; Chris@16: Chris@16: // fusion sequence Chris@16: template Chris@16: static type call(T_ const& t, mpl::false_, mpl::true_) Chris@16: { Chris@16: return fusion::at_c<0>(t); Chris@16: } Chris@16: Chris@16: // container Chris@16: template Chris@16: static type call(T_ const& t, mpl::true_, IsSequence) Chris@16: { Chris@16: return t[0]; Chris@16: } Chris@16: Chris@16: // not a container and not a fusion sequence Chris@16: template Chris@16: static type call(T_ const& t, mpl::false_, mpl::false_) Chris@16: { Chris@16: return t; Chris@16: } Chris@16: Chris@16: static type call(T const& t) Chris@16: { Chris@16: typedef typename traits::is_container::type is_container; Chris@16: typedef typename fusion::traits::is_sequence::type is_sequence; Chris@16: Chris@16: return call(t, is_container(), is_sequence()); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct symbols_lookup Chris@16: { Chris@16: typedef Attribute const& type; Chris@16: Chris@16: static type call(Attribute const& t) Chris@16: { Chris@16: return t; Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct symbols_value Chris@16: { Chris@16: typedef Chris@16: mpl::eval_if Chris@16: , traits::detail::value_at_c Chris@16: , mpl::identity > sequence_type; Chris@16: typedef typename Chris@16: mpl::eval_if Chris@16: , traits::container_value Chris@16: , sequence_type>::type type; Chris@16: Chris@16: // fusion sequence Chris@16: template Chris@16: static type call(T_ const& t, mpl::false_, mpl::true_) Chris@16: { Chris@16: return fusion::at_c<1>(t); Chris@16: } Chris@16: Chris@16: // container Chris@16: template Chris@16: static type call(T_ const& t, mpl::true_, IsSequence) Chris@16: { Chris@16: return t[1]; Chris@16: } Chris@16: Chris@16: // not a container nor a fusion sequence Chris@16: template Chris@16: static type call(T_ const&, mpl::false_, mpl::false_) Chris@16: { Chris@16: return unused; Chris@16: } Chris@16: Chris@16: static type call(T const& t) Chris@16: { Chris@16: typedef typename traits::is_container::type is_container; Chris@16: typedef typename fusion::traits::is_sequence::type is_sequence; Chris@16: Chris@16: return call(t, is_container(), is_sequence()); Chris@16: } Chris@16: }; Chris@16: Chris@16: template Chris@16: struct symbols_value Chris@16: { Chris@16: typedef unused_type type; Chris@16: Chris@16: static type call(Attribute const&) Chris@16: { Chris@16: return unused; Chris@16: } Chris@16: }; Chris@16: }}} Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////////// Chris@16: namespace boost { namespace spirit { namespace karma Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct symbols_lookup Chris@16: : mpl::if_< Chris@16: traits::not_is_unused Chris@16: , std::map Chris@16: , std::set Chris@16: > Chris@16: {}; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: namespace detail Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct generate_encoded Chris@16: { Chris@16: typedef typename Chris@16: proto::terminal >::type Chris@16: encoding_type; Chris@16: Chris@16: template Chris@16: static bool call(OutputIterator& sink, Expr const& expr Chris@16: , Attribute const& attr) Chris@16: { Chris@16: encoding_type const encoding = encoding_type(); Chris@16: return karma::generate(sink, encoding[expr], attr); Chris@16: } Chris@16: }; Chris@16: Chris@16: template <> Chris@16: struct generate_encoded Chris@16: { Chris@16: template Chris@16: static bool call(OutputIterator& sink, Expr const& expr Chris@16: , Attribute const& attr) Chris@16: { Chris@16: return karma::generate(sink, expr, attr); Chris@16: } Chris@16: }; Chris@16: } Chris@16: Chris@16: template < Chris@16: typename Attribute = char, typename T = unused_type Chris@16: , typename Lookup = typename symbols_lookup::type Chris@16: , typename CharEncoding = unused_type, typename Tag = unused_type> Chris@16: struct symbols Chris@16: : proto::extends< Chris@16: typename proto::terminal< Chris@16: reference > Chris@16: >::type Chris@16: , symbols > Chris@16: , primitive_generator< Chris@16: symbols > Chris@16: { Chris@16: typedef T value_type; // the value associated with each entry Chris@16: Chris@16: typedef reference reference_; Chris@16: typedef typename proto::terminal::type terminal; Chris@16: typedef proto::extends base_type; Chris@16: Chris@16: template Chris@16: struct attribute Chris@16: { Chris@16: typedef Attribute type; Chris@16: }; Chris@16: Chris@16: symbols(std::string const& name = "symbols") Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(new Lookup()) Chris@16: , name_(name) Chris@16: {} Chris@16: Chris@16: symbols(symbols const& syms) Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(syms.lookup) Chris@16: , name_(syms.name_) Chris@16: {} Chris@16: Chris@16: template Chris@16: symbols(symbols const& syms) Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(syms.lookup) Chris@16: , name_(syms.name_) Chris@16: {} Chris@16: Chris@16: template Chris@16: symbols(Symbols const& syms, Data const& data Chris@16: , std::string const& name = "symbols") Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(new Lookup()) Chris@16: , name_(name) Chris@16: { Chris@16: typename range_const_iterator::type si = boost::begin(syms); Chris@16: typename range_const_iterator::type di = boost::begin(data); Chris@16: while (si != boost::end(syms)) Chris@16: add(*si++, *di++); Chris@16: } Chris@16: Chris@16: symbols& Chris@16: operator=(symbols const& rhs) Chris@16: { Chris@16: *lookup = *rhs.lookup; Chris@16: name_ = rhs.name_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: symbols& Chris@16: operator=(symbols const& rhs) Chris@16: { Chris@16: *lookup = *rhs.lookup; Chris@16: name_ = rhs.name_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void clear() Chris@16: { Chris@16: lookup->clear(); Chris@16: } Chris@16: Chris@16: struct adder; Chris@16: struct remover; Chris@16: Chris@16: template Chris@16: adder const& Chris@16: operator=(std::pair const& p) Chris@16: { Chris@16: lookup->clear(); Chris@16: return add(p.first, p.second); Chris@16: } Chris@16: Chris@16: template Chris@16: friend adder const& Chris@16: operator+= (symbols& sym, std::pair const& p) Chris@16: { Chris@16: return sym.add(p.first, p.second); Chris@16: } Chris@16: Chris@16: template Chris@16: friend remover const& Chris@16: operator-= (symbols& sym, Attr const& attr) Chris@16: { Chris@16: return sym.remove(attr); Chris@16: } Chris@16: Chris@16: #if defined(BOOST_NO_CXX11_RVALUE_REFERENCES) Chris@16: // non-const version needed to suppress proto's += kicking in Chris@16: template Chris@16: friend adder const& Chris@16: operator+= (symbols& sym, std::pair& p) Chris@16: { Chris@16: return sym.add(p.first, p.second); Chris@16: } Chris@16: Chris@16: // non-const version needed to suppress proto's -= kicking in Chris@16: template Chris@16: friend remover const& Chris@16: operator-= (symbols& sym, Attr& attr) Chris@16: { Chris@16: return sym.remove(attr); Chris@16: } Chris@16: #else Chris@16: // for rvalue references Chris@16: template Chris@16: friend adder const& Chris@16: operator+= (symbols& sym, std::pair&& p) Chris@16: { Chris@16: return sym.add(p.first, p.second); Chris@16: } Chris@16: Chris@16: // for rvalue references Chris@16: template Chris@16: friend remover const& Chris@16: operator-= (symbols& sym, Attr&& attr) Chris@16: { Chris@16: return sym.remove(attr); Chris@16: } Chris@16: #endif Chris@16: template Chris@16: void for_each(F f) const Chris@16: { Chris@16: std::for_each(lookup->begin(), lookup->end(), f); Chris@16: } Chris@16: Chris@16: template Chris@16: value_type* find(Attr const& attr) Chris@16: { Chris@16: typename Lookup::iterator it = lookup->find(attr); Chris@16: return (it != lookup->end()) ? &(*it).second : 0; Chris@16: } Chris@16: Chris@16: template Chris@16: value_type& at(Attr const& attr) Chris@16: { Chris@16: return (*lookup)[attr]; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: bool generate(OutputIterator& sink, Context&, Delimiter const& d Chris@16: , Attr const& attr) const Chris@16: { Chris@16: typename Lookup::iterator it = lookup->find( Chris@16: traits::symbols_lookup::call(attr)); Chris@16: if (it == lookup->end()) Chris@16: return false; Chris@16: Chris@16: return karma::detail::generate_encoded::call( Chris@16: sink, (*it).second Chris@16: , traits::symbols_value::call(attr)) && Chris@16: karma::delimit_out(sink, d); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context&) const Chris@16: { Chris@16: return info(name_); Chris@16: } Chris@16: Chris@16: void name(std::string const &str) Chris@16: { Chris@16: name_ = str; Chris@16: } Chris@16: std::string const &name() const Chris@16: { Chris@16: return name_; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: struct adder Chris@16: { Chris@16: template Chris@16: struct result { typedef adder const& type; }; Chris@16: Chris@16: adder(symbols& sym) Chris@16: : sym(sym) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: adder const& Chris@16: operator()(Attr const& attr, T const& val = T()) const Chris@16: { Chris@16: sym.lookup->insert(typename Lookup::value_type(attr, val)); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: adder const& Chris@16: operator, (Attr const& attr) const Chris@16: { Chris@16: sym.lookup->insert(typename Lookup::value_type(attr, T())); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: symbols& sym; Chris@16: Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: adder& operator= (adder const&); Chris@16: }; Chris@16: Chris@16: struct remover Chris@16: { Chris@16: template Chris@16: struct result { typedef remover const& type; }; Chris@16: Chris@16: remover(symbols& sym) Chris@16: : sym(sym) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: remover const& Chris@16: operator()(Attr const& attr) const Chris@16: { Chris@16: sym.lookup->erase(attr); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: remover const& Chris@16: operator, (Attr const& attr) const Chris@16: { Chris@16: sym.lookup->erase(attr); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: symbols& sym; Chris@16: Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: remover& operator= (remover const&); Chris@16: }; Chris@16: Chris@16: adder add; Chris@16: remover remove; Chris@16: shared_ptr lookup; Chris@16: std::string name_; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // specialization for unused stored type Chris@16: template < Chris@16: typename Attribute, typename Lookup Chris@16: , typename CharEncoding, typename Tag> Chris@16: struct symbols Chris@16: : proto::extends< Chris@16: typename proto::terminal< Chris@16: spirit::karma::reference< Chris@16: symbols > Chris@16: >::type Chris@16: , symbols Chris@16: > Chris@16: , spirit::karma::generator< Chris@16: symbols > Chris@16: { Chris@16: typedef unused_type value_type; // the value associated with each entry Chris@16: Chris@16: typedef spirit::karma::reference reference_; Chris@16: typedef typename proto::terminal::type terminal; Chris@16: typedef proto::extends base_type; Chris@16: Chris@16: template Chris@16: struct attribute Chris@16: { Chris@16: typedef Attribute type; Chris@16: }; Chris@16: Chris@16: symbols(std::string const& name = "symbols") Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(new Lookup()) Chris@16: , name_(name) Chris@16: {} Chris@16: Chris@16: symbols(symbols const& syms) Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(syms.lookup) Chris@16: , name_(syms.name_) Chris@16: {} Chris@16: Chris@16: template Chris@16: symbols(symbols const& syms) Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(syms.lookup) Chris@16: , name_(syms.name_) Chris@16: {} Chris@16: Chris@16: template Chris@16: symbols(Symbols const& syms, Data const& data Chris@16: , std::string const& name = "symbols") Chris@16: : base_type(terminal::make(reference_(*this))) Chris@16: , add(*this) Chris@16: , remove(*this) Chris@16: , lookup(new Lookup()) Chris@16: , name_(name) Chris@16: { Chris@16: typename range_const_iterator::type si = boost::begin(syms); Chris@16: typename range_const_iterator::type di = boost::begin(data); Chris@16: while (si != boost::end(syms)) Chris@16: add(*si++, *di++); Chris@16: } Chris@16: Chris@16: symbols& Chris@16: operator=(symbols const& rhs) Chris@16: { Chris@16: *lookup = *rhs.lookup; Chris@16: name_ = rhs.name_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: symbols& Chris@16: operator=(symbols const& rhs) Chris@16: { Chris@16: *lookup = *rhs.lookup; Chris@16: name_ = rhs.name_; Chris@16: return *this; Chris@16: } Chris@16: Chris@16: void clear() Chris@16: { Chris@16: lookup->clear(); Chris@16: } Chris@16: Chris@16: struct adder; Chris@16: struct remover; Chris@16: Chris@16: template Chris@16: adder const& Chris@16: operator=(Attr const& attr) Chris@16: { Chris@16: lookup->clear(); Chris@16: return add(attr); Chris@16: } Chris@16: Chris@16: template Chris@16: friend adder const& Chris@16: operator+= (symbols& sym, Attr const& attr) Chris@16: { Chris@16: return sym.add(attr); Chris@16: } Chris@16: Chris@16: template Chris@16: friend remover const& Chris@16: operator-= (symbols& sym, Attr const& attr) Chris@16: { Chris@16: return sym.remove(attr); Chris@16: } Chris@16: Chris@16: // non-const version needed to suppress proto's += kicking in Chris@16: template Chris@16: friend adder const& Chris@16: operator+= (symbols& sym, Attr& attr) Chris@16: { Chris@16: return sym.add(attr); Chris@16: } Chris@16: Chris@16: // non-const version needed to suppress proto's -= kicking in Chris@16: template Chris@16: friend remover const& Chris@16: operator-= (symbols& sym, Attr& attr) Chris@16: { Chris@16: return sym.remove(attr); Chris@16: } Chris@16: Chris@16: template Chris@16: void for_each(F f) const Chris@16: { Chris@16: std::for_each(lookup->begin(), lookup->end(), f); Chris@16: } Chris@16: Chris@16: template Chris@16: value_type const* find(Attr const& attr) Chris@16: { Chris@16: typename Lookup::iterator it = lookup->find(attr); Chris@16: return (it != lookup->end()) ? &unused : 0; Chris@16: } Chris@16: Chris@16: template Chris@16: value_type at(Attr const& attr) Chris@16: { Chris@16: typename Lookup::iterator it = lookup->find(attr); Chris@16: if (it == lookup->end()) Chris@16: add(attr); Chris@16: return unused; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: bool generate(OutputIterator& sink, Context&, Delimiter const& d Chris@16: , Attr const& attr) const Chris@16: { Chris@16: typename Lookup::iterator it = lookup->find( Chris@16: traits::symbols_lookup::call(attr)); Chris@16: if (it == lookup->end()) Chris@16: return false; Chris@16: Chris@16: return karma::detail::generate_encoded:: Chris@16: call(sink Chris@16: , traits::symbols_lookup::call(attr) Chris@16: , unused) && Chris@16: karma::delimit_out(sink, d); Chris@16: } Chris@16: Chris@16: template Chris@16: info what(Context&) const Chris@16: { Chris@16: return info(name_); Chris@16: } Chris@16: Chris@16: void name(std::string const &str) Chris@16: { Chris@16: name_ = str; Chris@16: } Chris@16: std::string const &name() const Chris@16: { Chris@16: return name_; Chris@16: } Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////// Chris@16: struct adder Chris@16: { Chris@16: template Chris@16: struct result { typedef adder const& type; }; Chris@16: Chris@16: adder(symbols& sym) Chris@16: : sym(sym) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: adder const& Chris@16: operator()(Attr const& attr) const Chris@16: { Chris@16: sym.lookup->insert(attr); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: adder const& Chris@16: operator, (Attr const& attr) const Chris@16: { Chris@16: sym.lookup->insert(attr); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: symbols& sym; Chris@16: Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: adder& operator= (adder const&); Chris@16: }; Chris@16: Chris@16: struct remover Chris@16: { Chris@16: template Chris@16: struct result { typedef remover const& type; }; Chris@16: Chris@16: remover(symbols& sym) Chris@16: : sym(sym) Chris@16: { Chris@16: } Chris@16: Chris@16: template Chris@16: remover const& Chris@16: operator()(Attr const& attr) const Chris@16: { Chris@16: sym.lookup->erase(attr); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: template Chris@16: remover const& Chris@16: operator, (Attr const& attr) const Chris@16: { Chris@16: sym.lookup->erase(attr); Chris@16: return *this; Chris@16: } Chris@16: Chris@16: symbols& sym; Chris@16: Chris@16: private: Chris@16: // silence MSVC warning C4512: assignment operator could not be generated Chris@16: remover& operator= (remover const&); Chris@16: }; Chris@16: Chris@16: adder add; Chris@16: remover remove; Chris@16: shared_ptr lookup; Chris@16: std::string name_; Chris@16: }; Chris@16: Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: // Generator generators: make_xxx function (objects) Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct make_primitive< Chris@16: reference > Chris@16: , Modifiers> Chris@16: { Chris@16: static bool const lower = Chris@16: has_modifier >::value; Chris@16: static bool const upper = Chris@16: has_modifier >::value; Chris@16: Chris@16: typedef reference< Chris@16: symbols Chris@16: > reference_; Chris@16: Chris@16: typedef typename mpl::if_c< Chris@16: lower || upper Chris@16: , symbols< Chris@16: Attribute, T, Lookup Chris@16: , typename spirit::detail::get_encoding_with_case< Chris@16: Modifiers, unused_type, lower || upper>::type Chris@16: , typename detail::get_casetag::type> Chris@16: , reference_>::type Chris@16: result_type; Chris@16: Chris@16: result_type operator()(reference_ ref, unused_type) const Chris@16: { Chris@16: return result_type(ref.ref.get()); Chris@16: } Chris@16: }; Chris@16: }}} Chris@16: Chris@16: namespace boost { namespace spirit { namespace traits Chris@16: { Chris@16: /////////////////////////////////////////////////////////////////////////// Chris@16: template Chris@16: struct handles_container Chris@16: , Attr, Context, Iterator> Chris@16: : traits::is_container {}; Chris@16: }}} Chris@16: Chris@16: #if defined(BOOST_MSVC) Chris@16: # pragma warning(pop) Chris@16: #endif Chris@16: Chris@16: #endif Chris@16: