Mailinglist Archive: zypp-commit (172 mails)

< Previous Next >
[zypp-commit] <libzypp> master : Enhance xml::parseDefAssign to support Node attribute consumption and pre/post-processing.
  • From: Michael Andres <ma@xxxxxxx>
  • Date: Fri, 6 Feb 2009 12:02:09 +0100
  • Message-id: <E1LVOVz-0005No-Vk@xxxxxxxxxxxxxxxx>
ref: refs/heads/master
commit 9ab23d05bb23a284c1b06a28b5516a393746eb36
Author: Michael Andres <ma@xxxxxxx>
Date: Thu Feb 5 19:29:16 2009 +0100

Enhance xml::parseDefAssign to support Node attribute consumption and
pre/post-processing.
---
zypp/parser/ProductFileReader.cc | 28 ++--
zypp/parser/xml/ParseDef.cc | 33 ----
zypp/parser/xml/ParseDefConsume.h | 300 ++++++++++++++++++++++++++++---------
zypp/parser/xml/Reader.cc | 4 +-
4 files changed, 249 insertions(+), 116 deletions(-)

diff --git a/zypp/parser/ProductFileReader.cc b/zypp/parser/ProductFileReader.cc
index 1e6ef13..1f5bdfb 100644
--- a/zypp/parser/ProductFileReader.cc
+++ b/zypp/parser/ProductFileReader.cc
@@ -131,20 +131,20 @@ namespace zypp
, _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"]
@@ -152,11 +152,11 @@ namespace zypp
;

(*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
diff --git a/zypp/parser/xml/ParseDef.cc b/zypp/parser/xml/ParseDef.cc
index 59c73ce..2fdda63 100644
--- a/zypp/parser/xml/ParseDef.cc
+++ b/zypp/parser/xml/ParseDef.cc
@@ -30,39 +30,6 @@ using std::endl;
namespace zypp
{ /////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
- namespace debug
- { /////////////////////////////////////////////////////////////////
-
- template<class _Derived>
- struct TraceInstance
- {
- TraceInstance()
- { total(1); }
- TraceInstance( const TraceInstance & rhs )
- { total(1); }
- ~TraceInstance()
- { total(-1); }
- static unsigned & total( int cnt_r )
- {
- static unsigned _total = 0;
- _total += cnt_r;
- INT << "total += " << cnt_r << " => " << _total << endl;
- return _total;
- }
- };
-
- /////////////////////////////////////////////////////////////////
- } // namespace debug
- ///////////////////////////////////////////////////////////////////
- /////////////////////////////////////////////////////////////////
-} // namespace zypp
-///////////////////////////////////////////////////////////////////
-
-
-///////////////////////////////////////////////////////////////////
-namespace zypp
-{ /////////////////////////////////////////////////////////////////
- ///////////////////////////////////////////////////////////////////
namespace xml
{ /////////////////////////////////////////////////////////////////

diff --git a/zypp/parser/xml/ParseDefConsume.h
b/zypp/parser/xml/ParseDefConsume.h
index c34a9e0..2f75dc9 100644
--- a/zypp/parser/xml/ParseDefConsume.h
+++ b/zypp/parser/xml/ParseDefConsume.h
@@ -14,6 +14,7 @@

#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"

@@ -121,86 +122,249 @@ namespace zypp
///////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////
- //
- // 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
///////////////////////////////////////////////////////////////////
diff --git a/zypp/parser/xml/Reader.cc b/zypp/parser/xml/Reader.cc
index c8e9fd0..5f7c155 100644
--- a/zypp/parser/xml/Reader.cc
+++ b/zypp/parser/xml/Reader.cc
@@ -90,6 +90,7 @@ namespace zypp
stream_r.path().asString().c_str(), "utf-8",
XML_PARSE_PEDANTIC ) )
, _node( _reader )
{
+ MIL << "Start Parsing " << _stream << endl;
if ( ! _reader || ! stream_r.stream().good() )
ZYPP_THROW( Exception( "Bad input stream" ) );
// set error handler
@@ -111,6 +112,7 @@ namespace zypp
{
xmlFreeTextReader( _reader );
}
+ MIL << "Done Parsing " << _stream << endl;
}

XmlString Reader::nodeText()
@@ -127,7 +129,7 @@ namespace zypp
}
return XmlString();
}
-
+
///////////////////////////////////////////////////////////////////
//
// METHOD NAME : Reader::nextNode
--
To unsubscribe, e-mail: zypp-commit+unsubscribe@xxxxxxxxxxxx
For additional commands, e-mail: zypp-commit+help@xxxxxxxxxxxx

< Previous Next >
This Thread
  • No further messages