2f75dc9b2d631be225ff5756aa3e993a1985088f
[platform/upstream/libzypp.git] / zypp / parser / xml / ParseDefConsume.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/parser/xml/ParseDefConsume.h
10  *
11 */
12 #ifndef ZYPP_PARSER_XML_PARSEDEFCONSUME_H
13 #define ZYPP_PARSER_XML_PARSEDEFCONSUME_H
14
15 #include "zypp/base/PtrTypes.h"
16 #include "zypp/base/Function.h"
17 #include "zypp/base/Tr1hash.h"
18 #include "zypp/base/String.h"
19 #include "zypp/base/DefaultIntegral.h"
20
21 #include "zypp/parser/xml/Node.h"
22
23 ///////////////////////////////////////////////////////////////////
24 namespace zypp
25 { /////////////////////////////////////////////////////////////////
26   ///////////////////////////////////////////////////////////////////
27   namespace xml
28   { /////////////////////////////////////////////////////////////////
29
30     class Node;
31
32     ///////////////////////////////////////////////////////////////////
33     //
34     //  CLASS NAME : ParseDefConsume
35     //
36     /** Base class for ParseDef consumer.
37      */
38     struct ParseDefConsume
39     {
40       virtual ~ParseDefConsume();
41
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 );
46
47       virtual void startSubnode( const Node & _node );
48       virtual void doneSubnode ( const Node & _node );
49     };
50     ///////////////////////////////////////////////////////////////////
51
52     ///////////////////////////////////////////////////////////////////
53     //
54     //  CLASS NAME : ParseDefConsumeRedirect
55     //
56     /** ParseDef consumer redirecting all events to another consumer.
57      * \note Allocated <tt>ParseDefConsume *</tt> passed are
58      *       immediately wraped into a shared_ptr.
59     */
60     class ParseDefConsumeRedirect : public ParseDefConsume
61     {
62     public:
63       ParseDefConsumeRedirect();
64       ParseDefConsumeRedirect( const shared_ptr<ParseDefConsume> & target_r );
65       ParseDefConsumeRedirect( ParseDefConsume * allocatedTarget_r );
66       ParseDefConsumeRedirect( ParseDefConsume & target_r );
67
68       virtual ~ParseDefConsumeRedirect();
69
70     public:
71       void setRedirect( const shared_ptr<ParseDefConsume> & target_r );
72       void setRedirect( ParseDefConsume * allocatedTarget_r );
73       void setRedirect( ParseDefConsume & target_r );
74       void cancelRedirect();
75
76       shared_ptr<ParseDefConsume> getRedirect() const;
77
78     public:
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 );
85
86     private:
87       shared_ptr<ParseDefConsume> _target;
88     };
89     ///////////////////////////////////////////////////////////////////
90
91     ///////////////////////////////////////////////////////////////////
92     //
93     //  CLASS NAME : ParseDefConsumeCallback
94     //
95     /** ParseDef consumer that invokes callbacks.
96     */
97     class ParseDefConsumeCallback : public ParseDefConsume
98     {
99     public:
100       typedef function<void(const Node &)> Callback;
101
102       ParseDefConsumeCallback();
103
104       virtual ~ParseDefConsumeCallback();
105
106     public:
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 );
113
114     public:
115       Callback _start;
116       Callback _text;
117       Callback _cdata;
118       Callback _done;
119       Callback _startSubnode;
120       Callback _doneSubnode;
121     };
122     ///////////////////////////////////////////////////////////////////
123
124     ///////////////////////////////////////////////////////////////////
125     /** \ref parseDefAssign exposed details */
126     namespace parse_def_assign
127     { /////////////////////////////////////////////////////////////////
128      template <class _Type> struct Assigner;
129
130       typedef shared_ptr<Assigner<void> > AssignerRef;
131
132       /** Common interface to all Assigner types. */
133       template <>
134           struct Assigner<void>
135       {
136         virtual ~Assigner()
137         {}
138         virtual void assign( const char * text_r )
139         {}
140       };
141
142       /** Assigner assigns text to types constructible from \c char*.
143        * \see \ref assigner consvenience constructor.
144       */
145       template <class _Type>
146           struct Assigner : public Assigner<void>
147       {
148         Assigner(_Type & value_r )
149           : _value( &value_r )
150         {}
151
152         virtual void assign( const char * text_r )
153         { *_value = _Type( text_r ); }
154
155         private:
156           _Type * _value;
157       };
158
159       /** \name Assigner specialisation for numeric and boolean values.
160        *  \relates Assigner
161        */
162       //@{
163       template <>
164           inline void Assigner<short>::assign( const char * text_r )              { str::strtonum( text_r, *_value ); }
165       template <>
166           inline void Assigner<int>::assign( const char * text_r )                { str::strtonum( text_r, *_value ); }
167       template <>
168           inline void Assigner<long>::assign( const char * text_r )               { str::strtonum( text_r, *_value ); }
169       template <>
170           inline void Assigner<long long>::assign( const char * text_r )          { str::strtonum( text_r, *_value ); }
171       template <>
172           inline void Assigner<unsigned short>::assign( const char * text_r )     { str::strtonum( text_r, *_value ); }
173       template <>
174           inline void Assigner<unsigned>::assign( const char * text_r )           { str::strtonum( text_r, *_value ); }
175       template <>
176           inline void Assigner<unsigned long>::assign( const char * text_r )      { str::strtonum( text_r, *_value ); }
177       template <>
178           inline void Assigner<unsigned long long>::assign( const char * text_r ) { str::strtonum( text_r, *_value ); }
179
180       template <>
181           inline void Assigner<bool>::assign( const char * text_r ) { str::strToBoolNodefault( text_r, *_value ); }
182       //@}
183
184       /** \name \relates Assigner Convenience constructor */
185       //@{
186       template <class _Type>
187           inline AssignerRef assigner( _Type & value_r )
188       { return AssignerRef( new Assigner<_Type>( value_r ) ); }
189
190       template <class _Tp, _Tp _Initial>
191           inline AssignerRef assigner( DefaultIntegral<_Tp,_Initial> & value_r )
192       { return AssignerRef( new Assigner<_Tp>( value_r.get() ) ); }
193       //@}
194
195
196       /** \ref ParseDef consumer assigning \ref Node text and attribues values to variables.
197        *
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).
201        *
202        * You may also set a <tt>void( const Node & )</tt> notification
203        * callback which is invoked after the node was processed.
204        *
205        * \note Use and see \ref xml::parseDefAssign convenience constructor.
206        *
207        * \code
208        * // parsedef for '<setup attr="13">value</setup>'
209        * ParseDef( "attr", MANDTAORY, xml::parseDefAssign( data.value )
210        *                                                 ( "attr", data.attr ) )
211        * \endcode
212        */
213       struct Consumer : public ParseDefConsume
214       {
215         /** Extend \ref Consumer. */
216         void add( const AssignerRef & assigner_r )
217         { _text.push_back( assigner_r ); }
218
219         /** Extend \ref Consumer. */
220         void add( const std::string & attr_r, const AssignerRef & assigner_r )
221         { _attr[attr_r].push_back( assigner_r ); }
222
223         /** Set pre notification callback. */
224         void prenotify( function<void ( const Node & )> pre_r )
225         { _pre = pre_r; }
226
227         /** Set post notification callback. */
228         void postnotify( function<void ( const Node & )> post_r )
229         { _post = post_r; }
230
231         virtual void start( const xml::Node & node_r )
232         {
233           if ( _pre )
234             _pre( node_r );
235
236           if ( ! _attr.empty() )
237             for_( it, _attr.begin(), _attr.end() )
238               assign( it->second, node_r.getAttribute( it->first.c_str() ).c_str() );
239         }
240
241         virtual void text( const xml::Node & node_r )
242         {
243           if ( ! _text.empty() )
244             assign( _text, node_r.value().c_str() );
245         }
246
247         virtual void done( const xml::Node & node_r )
248         {
249           if ( _post )
250             _post( node_r );
251         }
252
253         private:
254           void assign( const std::vector<AssignerRef> & vec_r, const char * value_r )
255           {
256             if ( value_r )
257               for_( it, vec_r.begin(), vec_r.end() )
258                 (*it)->assign( value_r );
259           }
260
261         private:
262           std::tr1::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;
266       };
267
268       /** Helper class to build a \ref Consumer.
269        * \relates Consumer
270        *
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.
275        *
276        * You may also set a <tt>void( const Node & )</tt> notification
277        * callback which is invoked before/after the node was processed.
278        *
279        * \note Use and see \ref xml::parseDefAssign convenience constructor.
280       */
281       struct Builder
282       {
283         /** Contruct \ref Consumer. */
284         Builder()
285           : _ptr( new Consumer )
286         {}
287
288         /** Contruct \ref Consumer. */
289         template <class _Type>
290             Builder( _Type & value_r )
291           : _ptr( new Consumer )
292         { operator()( value_r ); }
293
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 ); }
299
300         /** Extend \ref Consumer. */
301         template <class _Type>
302             Builder & operator()( _Type & value_r )
303         { _ptr->add( assigner( value_r ) ); return *this; }
304
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; }
309
310         /** Set pre notification callback. */
311         Builder & operator<<( function<void ( const Node & )> done_r )
312         { _ptr->prenotify( done_r ); return *this; }
313
314         /** Set post notification callback. */
315         Builder & operator>>( function<void ( const Node & )> done_r )
316         { _ptr->postnotify( done_r ); return *this; }
317
318         /** Type conversion so this can be passed as node consumer to \ref ParseDef. */
319         operator shared_ptr<ParseDefConsume> () const
320         { return _ptr; }
321
322         private:
323           shared_ptr<Consumer> _ptr;
324       };
325       /////////////////////////////////////////////////////////////////
326     } // namespace parse_def_assign
327     ///////////////////////////////////////////////////////////////////
328
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
332      *
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.
337      *
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).
341      *
342      * \code
343      * void setupDone( const xml::Node & _node )
344      * { ... }
345      *
346      * // parsedef for '<setup attr="13">value</setup>'
347      * ParseDef( "attr", MANDTAORY,
348      *           xml::parseDefAssign( data.value )
349      *                              ( "attr", data.attr )
350      *                              >> &setupDone       );
351      * \endcode
352      *
353      * \see \ref xml::rnParse for more example.
354      */
355     //@{
356     inline parse_def_assign::Builder parseDefAssign()
357     { return parse_def_assign::Builder(); }
358
359     template <class _Type>
360         inline parse_def_assign::Builder parseDefAssign( _Type & value_r )
361     { return parse_def_assign::Builder( value_r ); }
362
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 ); }
366     //@}
367
368     /////////////////////////////////////////////////////////////////
369   } // namespace xml
370   ///////////////////////////////////////////////////////////////////
371   /////////////////////////////////////////////////////////////////
372 } // namespace zypp
373 ///////////////////////////////////////////////////////////////////
374 #endif // ZYPP_PARSER_XML_PARSEDEFCONSUME_H