, _pdata( pdata_r )
{
(*this)
- ("vendor", OPTIONAL, xml::parseDefAssignText( _pdata._vendor ) )
- ("name", MANDTAORY, xml::parseDefAssignText( _pdata._name ) )
- ("version", MANDTAORY, xml::parseDefAssignText( _version ) )
- ("release", MANDTAORY, xml::parseDefAssignText( _release ) )
- ("arch", MANDTAORY, xml::parseDefAssignText( _pdata._arch ) )
- ("productline", OPTIONAL, xml::parseDefAssignText( _pdata._productline ) )
+ ("vendor", OPTIONAL, xml::parseDefAssign( _pdata._vendor ) )
+ ("name", MANDTAORY, xml::parseDefAssign( _pdata._name ) )
+ ("version", MANDTAORY, xml::parseDefAssign( _version ) )
+ ("release", MANDTAORY, xml::parseDefAssign( _release ) )
+ ("arch", MANDTAORY, xml::parseDefAssign( _pdata._arch ) )
+ ("productline", OPTIONAL, xml::parseDefAssign( _pdata._productline ) )
("register", OPTIONAL)
- ("updaterepokey", OPTIONAL, xml::parseDefAssignText( _pdata._updaterepokey ) )
+ ("updaterepokey", OPTIONAL, xml::parseDefAssign( _pdata._updaterepokey ) )
("upgrades", OPTIONAL)
;
(*this)["register"]
- ("target", OPTIONAL, xml::parseDefAssignText( _pdata._registerTarget ) )
- ("release", OPTIONAL, xml::parseDefAssignText( _pdata._registerRelease ) )
+ ("target", OPTIONAL, xml::parseDefAssign( _pdata._registerTarget ) )
+ ("release", OPTIONAL, xml::parseDefAssign( _pdata._registerRelease ) )
;
(*this)["upgrades"]
;
(*this)["upgrades"]["upgrade"]
- ("name", OPTIONAL, xml::parseDefAssignText( _upgrade._name ) )
- ("summary", OPTIONAL, xml::parseDefAssignText( _upgrade._summary ) )
- ("repository", OPTIONAL, xml::parseDefAssignText( _upgrade._repository ) )
- ("notify", OPTIONAL, xml::parseDefAssignText( _upgrade._notify ) )
- ("status", OPTIONAL, xml::parseDefAssignText( _upgrade._status ) )
+ ("name", OPTIONAL, xml::parseDefAssign( _upgrade._name ) )
+ ("summary", OPTIONAL, xml::parseDefAssign( _upgrade._summary ) )
+ ("repository", OPTIONAL, xml::parseDefAssign( _upgrade._repository ) )
+ ("notify", OPTIONAL, xml::parseDefAssign( _upgrade._notify ) )
+ ("status", OPTIONAL, xml::parseDefAssign( _upgrade._status ) )
;
// Not a clean way to collect the END_ELEMENT calls, but
#include "zypp/base/PtrTypes.h"
#include "zypp/base/Function.h"
+#include "zypp/base/Tr1hash.h"
#include "zypp/base/String.h"
#include "zypp/base/DefaultIntegral.h"
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
- //
- // CLASS NAME : ParseDefAssignText<_Type>
- //
- /** Assign a \ref Node text to types constructible from \c char*.
- * \code
- * struct ProductNode : public xml::ParseDef
- * {
- * ProductNode( ProductFileData::Impl & pdata_r )
- * : ParseDef( "product", MANDTAORY )
- * {
- * (*this)
- * ("vendor", OPTIONAL, parseDefAssignText( _vendor ) )
- * ("name", MANDTAORY, parseDefAssignText( _name ) )
- * ...
- * }
- *
- * std::string _vendor;
- * std::string _name;
- * };
- * \endcode
- */
- template <class _Type>
- struct ParseDefAssignText : public xml::ParseDefConsume
- {
- ParseDefAssignText( _Type & value_r )
- : _value( &value_r )
- {}
+ /** \ref parseDefAssign exposed details */
+ namespace parse_def_assign
+ { /////////////////////////////////////////////////////////////////
+ template <class _Type> struct Assigner;
+
+ typedef shared_ptr<Assigner<void> > AssignerRef;
- virtual void text( const xml::Node & node_r )
+ /** Common interface to all Assigner types. */
+ template <>
+ struct Assigner<void>
{
- *_value = _Type( node_r.value().c_str() );
- }
+ virtual ~Assigner()
+ {}
+ virtual void assign( const char * text_r )
+ {}
+ };
- private:
- _Type * _value;
- };
+ /** Assigner assigns text to types constructible from \c char*.
+ * \see \ref assigner consvenience constructor.
+ */
+ template <class _Type>
+ struct Assigner : public Assigner<void>
+ {
+ Assigner(_Type & value_r )
+ : _value( &value_r )
+ {}
- /** \name ParseDefAssignText specialisation for numeric and boolean values.
- * \relates ParseDefAssignText
- */
- //@{
- template <>
- inline void ParseDefAssignText<short>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<int>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<long>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<long long>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<unsigned short>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<unsigned>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<unsigned long>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<unsigned long long>::text( const xml::Node & node_r ) { str::strtonum( node_r.value().c_str(), *_value ); }
- template <>
- inline void ParseDefAssignText<bool>::text( const xml::Node & node_r ) { str::strToBoolNodefault( node_r.value().c_str(), *_value ); }
- //@}
+ virtual void assign( const char * text_r )
+ { *_value = _Type( text_r ); }
+
+ private:
+ _Type * _value;
+ };
+
+ /** \name Assigner specialisation for numeric and boolean values.
+ * \relates Assigner
+ */
+ //@{
+ template <>
+ inline void Assigner<short>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+ template <>
+ inline void Assigner<int>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+ template <>
+ inline void Assigner<long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+ template <>
+ inline void Assigner<long long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+ template <>
+ inline void Assigner<unsigned short>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+ template <>
+ inline void Assigner<unsigned>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+ template <>
+ inline void Assigner<unsigned long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+ template <>
+ inline void Assigner<unsigned long long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
+
+ template <>
+ inline void Assigner<bool>::assign( const char * text_r ) { str::strToBoolNodefault( text_r, *_value ); }
+ //@}
+
+ /** \name \relates Assigner Convenience constructor */
+ //@{
+ template <class _Type>
+ inline AssignerRef assigner( _Type & value_r )
+ { return AssignerRef( new Assigner<_Type>( value_r ) ); }
+
+ template <class _Tp, _Tp _Initial>
+ inline AssignerRef assigner( DefaultIntegral<_Tp,_Initial> & value_r )
+ { return AssignerRef( new Assigner<_Tp>( value_r.get() ) ); }
+ //@}
+
+
+ /** \ref ParseDef consumer assigning \ref Node text and attribues values to variables.
+ *
+ * This can be used with all types supported by \ref Assigner.
+ * Basically all types constructible from \c char*, or where a
+ * specialisation exists (e.g. numeric and bool).
+ *
+ * You may also set a <tt>void( const Node & )</tt> notification
+ * callback which is invoked after the node was processed.
+ *
+ * \note Use and see \ref xml::parseDefAssign convenience constructor.
+ *
+ * \code
+ * // parsedef for '<setup attr="13">value</setup>'
+ * ParseDef( "attr", MANDTAORY, xml::parseDefAssign( data.value )
+ * ( "attr", data.attr ) )
+ * \endcode
+ */
+ struct Consumer : public ParseDefConsume
+ {
+ /** Extend \ref Consumer. */
+ void add( const AssignerRef & assigner_r )
+ { _text.push_back( assigner_r ); }
+
+ /** Extend \ref Consumer. */
+ void add( const std::string & attr_r, const AssignerRef & assigner_r )
+ { _attr[attr_r].push_back( assigner_r ); }
+
+ /** Set pre notification callback. */
+ void prenotify( function<void ( const Node & )> pre_r )
+ { _pre = pre_r; }
+
+ /** Set post notification callback. */
+ void postnotify( function<void ( const Node & )> post_r )
+ { _post = post_r; }
+
+ virtual void start( const xml::Node & node_r )
+ {
+ if ( _pre )
+ _pre( node_r );
+
+ if ( ! _attr.empty() )
+ for_( it, _attr.begin(), _attr.end() )
+ assign( it->second, node_r.getAttribute( it->first.c_str() ).c_str() );
+ }
- /** \name ParseDefAssignText Convenience constructor.
- * \relates ParseDefAssignText
+ virtual void text( const xml::Node & node_r )
+ {
+ if ( ! _text.empty() )
+ assign( _text, node_r.value().c_str() );
+ }
+
+ virtual void done( const xml::Node & node_r )
+ {
+ if ( _post )
+ _post( node_r );
+ }
+
+ private:
+ void assign( const std::vector<AssignerRef> & vec_r, const char * value_r )
+ {
+ if ( value_r )
+ for_( it, vec_r.begin(), vec_r.end() )
+ (*it)->assign( value_r );
+ }
+
+ private:
+ std::tr1::unordered_map<std::string, std::vector<AssignerRef> > _attr;
+ std::vector<AssignerRef> _text;
+ function<void ( const Node & )> _pre;
+ function<void ( const Node & )> _post;
+ };
+
+ /** Helper class to build a \ref Consumer.
+ * \relates Consumer
+ *
+ * The class constructs the consumer, allows to extend it via
+ * \ref operator(), and provides a conversion to
+ * \c shared_ptr<ParseDefConsume>, so it can be passed as a
+ * node consumer to \ref ParseDef.
+ *
+ * You may also set a <tt>void( const Node & )</tt> notification
+ * callback which is invoked before/after the node was processed.
+ *
+ * \note Use and see \ref xml::parseDefAssign convenience constructor.
+ */
+ struct Builder
+ {
+ /** Contruct \ref Consumer. */
+ Builder()
+ : _ptr( new Consumer )
+ {}
+
+ /** Contruct \ref Consumer. */
+ template <class _Type>
+ Builder( _Type & value_r )
+ : _ptr( new Consumer )
+ { operator()( value_r ); }
+
+ /** Contruct \ref Consumer. */
+ template <class _Type>
+ Builder( const std::string & attr_r, _Type & value_r )
+ : _ptr( new Consumer )
+ { operator()( attr_r, value_r ); }
+
+ /** Extend \ref Consumer. */
+ template <class _Type>
+ Builder & operator()( _Type & value_r )
+ { _ptr->add( assigner( value_r ) ); return *this; }
+
+ /** Extend \ref Consumer. */
+ template <class _Type>
+ Builder & operator()( const std::string & attr_r, _Type & value_r )
+ { _ptr->add( attr_r, assigner( value_r ) ); return *this; }
+
+ /** Set pre notification callback. */
+ Builder & operator<<( function<void ( const Node & )> done_r )
+ { _ptr->prenotify( done_r ); return *this; }
+
+ /** Set post notification callback. */
+ Builder & operator>>( function<void ( const Node & )> done_r )
+ { _ptr->postnotify( done_r ); return *this; }
+
+ /** Type conversion so this can be passed as node consumer to \ref ParseDef. */
+ operator shared_ptr<ParseDefConsume> () const
+ { return _ptr; }
+
+ private:
+ shared_ptr<Consumer> _ptr;
+ };
+ /////////////////////////////////////////////////////////////////
+ } // namespace parse_def_assign
+ ///////////////////////////////////////////////////////////////////
+
+ /** \name \ref ParseDef consumer assigning \ref Node text and attribues values to variables.
+ * \relates parse_def_assign::Consumer
+ * \relates parse_def_assign::Builder
+ *
+ * This function allows convenient contruction of a \ref parse_def_assign::Consumer
+ * to be passed as \ref Node conssumer to \ref ParseDef. Simply list each attributes
+ * name together with the variable it's value should be assigned to. If the attribute
+ * name is omitted, the nodes text value gets assigned.
+ *
+ * Target variables can be of any type tsupported by \ref Assigner.
+ * Basically all types constructible from \c char*, or where a
+ * specialisation exists (e.g. numeric and bool).
*
- * This returns a \c shared_ptr<xml::ParseDefConsume> ready to be passed
- * to a \ref ParseDef node.
+ * \code
+ * void setupDone( const xml::Node & _node )
+ * { ... }
+ *
+ * // parsedef for '<setup attr="13">value</setup>'
+ * ParseDef( "attr", MANDTAORY,
+ * xml::parseDefAssign( data.value )
+ * ( "attr", data.attr )
+ * >> &setupDone );
+ * \endcode
+ *
+ * \see \ref xml::rnParse for more example.
*/
//@{
+ inline parse_def_assign::Builder parseDefAssign()
+ { return parse_def_assign::Builder(); }
+
template <class _Type>
- shared_ptr<xml::ParseDefConsume> parseDefAssignText( _Type & value_r )
- { return shared_ptr<xml::ParseDefConsume>( new ParseDefAssignText<_Type>( value_r ) ); }
+ inline parse_def_assign::Builder parseDefAssign( _Type & value_r )
+ { return parse_def_assign::Builder( value_r ); }
- template<class _Tp, _Tp _Initial>
- shared_ptr<xml::ParseDefConsume> parseDefAssignText( DefaultIntegral<_Tp,_Initial> & value_r )
- { return shared_ptr<xml::ParseDefConsume>( new ParseDefAssignText<_Tp>( value_r.get() ) ); }
+ template <class _Type>
+ inline parse_def_assign::Builder parseDefAssign( const std::string & attr_r, _Type & value_r )
+ { return parse_def_assign::Builder( attr_r, value_r ); }
//@}
- ///////////////////////////////////////////////////////////////////
-
-
/////////////////////////////////////////////////////////////////
} // namespace xml
///////////////////////////////////////////////////////////////////