ba559ee40b667c625d72c77ac8c7fe4c2aed9a67
[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/Hash.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 Tp> 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 convenience constructor.
144       */
145       template <class Tp>
146       struct Assigner : public Assigner<void>
147       {
148         Assigner( Tp & value_r )
149           : _value( &value_r )
150         {}
151
152         virtual void assign( const char * text_r )
153         { *_value = Tp( text_r ); }
154
155         private:
156           Tp * _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       template <>
180           inline void Assigner<bool>::assign( const char * text_r )               { str::strToBoolNodefault( text_r, *_value ); }
181       //@}
182
183       /** \name \relates Assigner Convenience constructor */
184       //@{
185       template <class Tp>
186           inline AssignerRef assigner( Tp & value_r )
187       { return AssignerRef( new Assigner<Tp>( value_r ) ); }
188
189       template <class Tp, Tp TInitial>
190           inline AssignerRef assigner( DefaultIntegral<Tp,TInitial> & value_r )
191       { return AssignerRef( new Assigner<Tp>( value_r.get() ) ); }
192       //@}
193
194
195       /** \ref ParseDef consumer assigning \ref Node text and attribues values to variables.
196        *
197        * This can be used with all types supported by \ref Assigner.
198        * Basically all types constructible from \c char*, or where a
199        * specialisation exists (e.g. numeric and bool).
200        *
201        * You may also set a <tt>void( const Node & )</tt> notification
202        * callback which is invoked after the node was processed.
203        *
204        * \note Use and see \ref xml::parseDefAssign convenience constructor.
205        *
206        * \code
207        * // parsedef for '<setup attr="13">value</setup>'
208        * ParseDef( "attr", MANDTAORY, xml::parseDefAssign( data.value )
209        *                                                 ( "attr", data.attr ) )
210        * \endcode
211        */
212       struct Consumer : public ParseDefConsume
213       {
214         /** Extend \ref Consumer. */
215         void add( const AssignerRef & assigner_r )
216         { _text.push_back( assigner_r ); }
217
218         /** Extend \ref Consumer. */
219         void add( const std::string & attr_r, const AssignerRef & assigner_r )
220         { _attr[attr_r].push_back( assigner_r ); }
221
222         /** Set pre notification callback. */
223         void prenotify( function<void ( const Node & )> pre_r )
224         { _pre = pre_r; }
225
226         /** Set post notification callback. */
227         void postnotify( function<void ( const Node & )> post_r )
228         { _post = post_r; }
229
230         virtual void start( const xml::Node & node_r )
231         {
232           if ( _pre )
233             _pre( node_r );
234
235           if ( ! _attr.empty() )
236             for_( it, _attr.begin(), _attr.end() )
237               assign( it->second, node_r.getAttribute( it->first.c_str() ).c_str() );
238         }
239
240         virtual void text( const xml::Node & node_r )
241         {
242           if ( ! _text.empty() )
243             assign( _text, node_r.value().c_str() );
244         }
245
246         virtual void done( const xml::Node & node_r )
247         {
248           if ( _post )
249             _post( node_r );
250         }
251
252         private:
253           void assign( const std::vector<AssignerRef> & vec_r, const char * value_r )
254           {
255             if ( value_r )
256               for_( it, vec_r.begin(), vec_r.end() )
257                 (*it)->assign( value_r );
258           }
259
260         private:
261           std::unordered_map<std::string, std::vector<AssignerRef> > _attr;
262           std::vector<AssignerRef>                                   _text;
263           function<void ( const Node & )>                            _pre;
264           function<void ( const Node & )>                            _post;
265       };
266
267       /** Helper class to build a \ref Consumer.
268        * \relates Consumer
269        *
270        * The class constructs the consumer, allows to extend it via
271        * \ref operator(), and provides a conversion to
272        * \c shared_ptr<ParseDefConsume>, so it can be passed as a
273        * node consumer to \ref ParseDef.
274        *
275        * You may also set a <tt>void( const Node & )</tt> notification
276        * callback which is invoked before/after the node was processed.
277        *
278        * \note Use and see \ref xml::parseDefAssign convenience constructor.
279       */
280       struct Builder
281       {
282         /** Contruct \ref Consumer. */
283         Builder()
284           : _ptr( new Consumer )
285         {}
286
287         /** Contruct \ref Consumer. */
288         template <class Tp>
289             Builder( Tp & value_r )
290           : _ptr( new Consumer )
291         { operator()( value_r ); }
292
293         /** Contruct \ref Consumer. */
294         template <class Tp>
295             Builder( const std::string & attr_r, Tp & value_r )
296           : _ptr( new Consumer )
297         {  operator()( attr_r, value_r ); }
298
299         /** Extend \ref Consumer. */
300         template <class Tp>
301             Builder & operator()( Tp & value_r )
302         { _ptr->add( assigner( value_r ) ); return *this; }
303
304         /** Extend \ref Consumer. */
305         template <class Tp>
306             Builder & operator()( const std::string & attr_r, Tp & value_r )
307         { _ptr->add( attr_r, assigner( value_r ) ); return *this; }
308
309         /** Set pre notification callback. */
310         Builder & operator<<( function<void ( const Node & )> done_r )
311         { _ptr->prenotify( done_r ); return *this; }
312
313         /** Set post notification callback. */
314         Builder & operator>>( function<void ( const Node & )> done_r )
315         { _ptr->postnotify( done_r ); return *this; }
316
317         /** Type conversion so this can be passed as node consumer to \ref ParseDef. */
318         operator shared_ptr<ParseDefConsume> () const
319         { return _ptr; }
320
321         private:
322           shared_ptr<Consumer> _ptr;
323       };
324       /////////////////////////////////////////////////////////////////
325     } // namespace parse_def_assign
326     ///////////////////////////////////////////////////////////////////
327
328     /** \name \ref ParseDef consumer assigning \ref Node text and attribues values to variables.
329      * \relates parse_def_assign::Consumer
330      * \relates parse_def_assign::Builder
331      *
332      * This function allows convenient contruction of a \ref parse_def_assign::Consumer
333      * to be passed as \ref Node conssumer to \ref ParseDef. Simply list each attributes
334      * name together with the variable it's value should be assigned to. If the attribute
335      * name is omitted, the nodes text value gets assigned.
336      *
337      * Target variables can be of any type tsupported by \ref Assigner.
338      * Basically all types constructible from \c char*, or where a
339      * specialisation exists (e.g. numeric and bool).
340      *
341      * \code
342      * void setupDone( const xml::Node & _node )
343      * { ... }
344      *
345      * // parsedef for '<setup attr="13">value</setup>'
346      * ParseDef( "attr", MANDTAORY,
347      *           xml::parseDefAssign( data.value )
348      *                              ( "attr", data.attr )
349      *                              >> &setupDone       );
350      * \endcode
351      *
352      * \see \ref xml::rnParse for more example.
353      */
354     //@{
355     inline parse_def_assign::Builder parseDefAssign()
356     { return parse_def_assign::Builder(); }
357
358     template <class Tp>
359         inline parse_def_assign::Builder parseDefAssign( Tp & value_r )
360     { return parse_def_assign::Builder( value_r ); }
361
362     template <class Tp>
363         inline parse_def_assign::Builder parseDefAssign( const std::string & attr_r, Tp & value_r )
364     { return parse_def_assign::Builder( attr_r, value_r ); }
365     //@}
366
367     /////////////////////////////////////////////////////////////////
368   } // namespace xml
369   ///////////////////////////////////////////////////////////////////
370   /////////////////////////////////////////////////////////////////
371 } // namespace zypp
372 ///////////////////////////////////////////////////////////////////
373 #endif // ZYPP_PARSER_XML_PARSEDEFCONSUME_H