1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/parser/xml/ParseDefConsume.h
12 #ifndef ZYPP_PARSER_XML_PARSEDEFCONSUME_H
13 #define ZYPP_PARSER_XML_PARSEDEFCONSUME_H
15 #include "zypp/base/PtrTypes.h"
16 #include "zypp/base/Function.h"
17 #include "zypp/base/Hash.h"
18 #include "zypp/base/String.h"
19 #include "zypp/base/DefaultIntegral.h"
21 #include "zypp/parser/xml/Node.h"
23 ///////////////////////////////////////////////////////////////////
25 { /////////////////////////////////////////////////////////////////
26 ///////////////////////////////////////////////////////////////////
28 { /////////////////////////////////////////////////////////////////
32 ///////////////////////////////////////////////////////////////////
34 // CLASS NAME : ParseDefConsume
36 /** Base class for ParseDef consumer.
38 struct ParseDefConsume
40 virtual ~ParseDefConsume();
42 virtual void start( const Node & _node );
43 virtual void text ( const Node & _node );
44 virtual void cdata( const Node & _node );
45 virtual void done ( const Node & _node );
47 virtual void startSubnode( const Node & _node );
48 virtual void doneSubnode ( const Node & _node );
50 ///////////////////////////////////////////////////////////////////
52 ///////////////////////////////////////////////////////////////////
54 // CLASS NAME : ParseDefConsumeRedirect
56 /** ParseDef consumer redirecting all events to another consumer.
57 * \note Allocated <tt>ParseDefConsume *</tt> passed are
58 * immediately wraped into a shared_ptr.
60 class ParseDefConsumeRedirect : public ParseDefConsume
63 ParseDefConsumeRedirect();
64 ParseDefConsumeRedirect( const shared_ptr<ParseDefConsume> & target_r );
65 ParseDefConsumeRedirect( ParseDefConsume * allocatedTarget_r );
66 ParseDefConsumeRedirect( ParseDefConsume & target_r );
68 virtual ~ParseDefConsumeRedirect();
71 void setRedirect( const shared_ptr<ParseDefConsume> & target_r );
72 void setRedirect( ParseDefConsume * allocatedTarget_r );
73 void setRedirect( ParseDefConsume & target_r );
74 void cancelRedirect();
76 shared_ptr<ParseDefConsume> getRedirect() const;
79 virtual void start( const Node & _node );
80 virtual void text ( const Node & _node );
81 virtual void cdata( const Node & _node );
82 virtual void done ( const Node & _node );
83 virtual void startSubnode( const Node & _node );
84 virtual void doneSubnode ( const Node & _node );
87 shared_ptr<ParseDefConsume> _target;
89 ///////////////////////////////////////////////////////////////////
91 ///////////////////////////////////////////////////////////////////
93 // CLASS NAME : ParseDefConsumeCallback
95 /** ParseDef consumer that invokes callbacks.
97 class ParseDefConsumeCallback : public ParseDefConsume
100 typedef function<void(const Node &)> Callback;
102 ParseDefConsumeCallback();
104 virtual ~ParseDefConsumeCallback();
107 virtual void start( const Node & node_r );
108 virtual void text( const Node & node_r );
109 virtual void cdata( const Node & node_r );
110 virtual void done( const Node & node_r );
111 virtual void startSubnode( const Node & node_r );
112 virtual void doneSubnode( const Node & node_r );
119 Callback _startSubnode;
120 Callback _doneSubnode;
122 ///////////////////////////////////////////////////////////////////
124 ///////////////////////////////////////////////////////////////////
125 /** \ref parseDefAssign exposed details */
126 namespace parse_def_assign
127 { /////////////////////////////////////////////////////////////////
128 template <class _Type> struct Assigner;
130 typedef shared_ptr<Assigner<void> > AssignerRef;
132 /** Common interface to all Assigner types. */
134 struct Assigner<void>
138 virtual void assign( const char * text_r )
142 /** Assigner assigns text to types constructible from \c char*.
143 * \see \ref assigner consvenience constructor.
145 template <class _Type>
146 struct Assigner : public Assigner<void>
148 Assigner(_Type & value_r )
152 virtual void assign( const char * text_r )
153 { *_value = _Type( text_r ); }
159 /** \name Assigner specialisation for numeric and boolean values.
164 inline void Assigner<short>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
166 inline void Assigner<int>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
168 inline void Assigner<long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
170 inline void Assigner<long long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
172 inline void Assigner<unsigned short>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
174 inline void Assigner<unsigned>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
176 inline void Assigner<unsigned long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
178 inline void Assigner<unsigned long long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
181 inline void Assigner<bool>::assign( const char * text_r ) { str::strToBoolNodefault( text_r, *_value ); }
184 /** \name \relates Assigner Convenience constructor */
186 template <class _Type>
187 inline AssignerRef assigner( _Type & value_r )
188 { return AssignerRef( new Assigner<_Type>( value_r ) ); }
190 template <class _Tp, _Tp _Initial>
191 inline AssignerRef assigner( DefaultIntegral<_Tp,_Initial> & value_r )
192 { return AssignerRef( new Assigner<_Tp>( value_r.get() ) ); }
196 /** \ref ParseDef consumer assigning \ref Node text and attribues values to variables.
198 * This can be used with all types supported by \ref Assigner.
199 * Basically all types constructible from \c char*, or where a
200 * specialisation exists (e.g. numeric and bool).
202 * You may also set a <tt>void( const Node & )</tt> notification
203 * callback which is invoked after the node was processed.
205 * \note Use and see \ref xml::parseDefAssign convenience constructor.
208 * // parsedef for '<setup attr="13">value</setup>'
209 * ParseDef( "attr", MANDTAORY, xml::parseDefAssign( data.value )
210 * ( "attr", data.attr ) )
213 struct Consumer : public ParseDefConsume
215 /** Extend \ref Consumer. */
216 void add( const AssignerRef & assigner_r )
217 { _text.push_back( assigner_r ); }
219 /** Extend \ref Consumer. */
220 void add( const std::string & attr_r, const AssignerRef & assigner_r )
221 { _attr[attr_r].push_back( assigner_r ); }
223 /** Set pre notification callback. */
224 void prenotify( function<void ( const Node & )> pre_r )
227 /** Set post notification callback. */
228 void postnotify( function<void ( const Node & )> post_r )
231 virtual void start( const xml::Node & node_r )
236 if ( ! _attr.empty() )
237 for_( it, _attr.begin(), _attr.end() )
238 assign( it->second, node_r.getAttribute( it->first.c_str() ).c_str() );
241 virtual void text( const xml::Node & node_r )
243 if ( ! _text.empty() )
244 assign( _text, node_r.value().c_str() );
247 virtual void done( const xml::Node & node_r )
254 void assign( const std::vector<AssignerRef> & vec_r, const char * value_r )
257 for_( it, vec_r.begin(), vec_r.end() )
258 (*it)->assign( value_r );
262 std::unordered_map<std::string, std::vector<AssignerRef> > _attr;
263 std::vector<AssignerRef> _text;
264 function<void ( const Node & )> _pre;
265 function<void ( const Node & )> _post;
268 /** Helper class to build a \ref Consumer.
271 * The class constructs the consumer, allows to extend it via
272 * \ref operator(), and provides a conversion to
273 * \c shared_ptr<ParseDefConsume>, so it can be passed as a
274 * node consumer to \ref ParseDef.
276 * You may also set a <tt>void( const Node & )</tt> notification
277 * callback which is invoked before/after the node was processed.
279 * \note Use and see \ref xml::parseDefAssign convenience constructor.
283 /** Contruct \ref Consumer. */
285 : _ptr( new Consumer )
288 /** Contruct \ref Consumer. */
289 template <class _Type>
290 Builder( _Type & value_r )
291 : _ptr( new Consumer )
292 { operator()( value_r ); }
294 /** Contruct \ref Consumer. */
295 template <class _Type>
296 Builder( const std::string & attr_r, _Type & value_r )
297 : _ptr( new Consumer )
298 { operator()( attr_r, value_r ); }
300 /** Extend \ref Consumer. */
301 template <class _Type>
302 Builder & operator()( _Type & value_r )
303 { _ptr->add( assigner( value_r ) ); return *this; }
305 /** Extend \ref Consumer. */
306 template <class _Type>
307 Builder & operator()( const std::string & attr_r, _Type & value_r )
308 { _ptr->add( attr_r, assigner( value_r ) ); return *this; }
310 /** Set pre notification callback. */
311 Builder & operator<<( function<void ( const Node & )> done_r )
312 { _ptr->prenotify( done_r ); return *this; }
314 /** Set post notification callback. */
315 Builder & operator>>( function<void ( const Node & )> done_r )
316 { _ptr->postnotify( done_r ); return *this; }
318 /** Type conversion so this can be passed as node consumer to \ref ParseDef. */
319 operator shared_ptr<ParseDefConsume> () const
323 shared_ptr<Consumer> _ptr;
325 /////////////////////////////////////////////////////////////////
326 } // namespace parse_def_assign
327 ///////////////////////////////////////////////////////////////////
329 /** \name \ref ParseDef consumer assigning \ref Node text and attribues values to variables.
330 * \relates parse_def_assign::Consumer
331 * \relates parse_def_assign::Builder
333 * This function allows convenient contruction of a \ref parse_def_assign::Consumer
334 * to be passed as \ref Node conssumer to \ref ParseDef. Simply list each attributes
335 * name together with the variable it's value should be assigned to. If the attribute
336 * name is omitted, the nodes text value gets assigned.
338 * Target variables can be of any type tsupported by \ref Assigner.
339 * Basically all types constructible from \c char*, or where a
340 * specialisation exists (e.g. numeric and bool).
343 * void setupDone( const xml::Node & _node )
346 * // parsedef for '<setup attr="13">value</setup>'
347 * ParseDef( "attr", MANDTAORY,
348 * xml::parseDefAssign( data.value )
349 * ( "attr", data.attr )
353 * \see \ref xml::rnParse for more example.
356 inline parse_def_assign::Builder parseDefAssign()
357 { return parse_def_assign::Builder(); }
359 template <class _Type>
360 inline parse_def_assign::Builder parseDefAssign( _Type & value_r )
361 { return parse_def_assign::Builder( value_r ); }
363 template <class _Type>
364 inline parse_def_assign::Builder parseDefAssign( const std::string & attr_r, _Type & value_r )
365 { return parse_def_assign::Builder( attr_r, value_r ); }
368 /////////////////////////////////////////////////////////////////
370 ///////////////////////////////////////////////////////////////////
371 /////////////////////////////////////////////////////////////////
373 ///////////////////////////////////////////////////////////////////
374 #endif // ZYPP_PARSER_XML_PARSEDEFCONSUME_H