- Resetting Delete Details in ResStatus correctly (bnc #391785)
[platform/upstream/libzypp.git] / devel / Example.createCapabilities.cc
1 #include <iostream>
2 #include <ctime>
3
4 #include <fstream>
5 #include <list>
6 #include <string>
7 #include <zypp/base/Logger.h>
8 #include <zypp/base/Exception.h>
9 #include <zypp/base/String.h>
10 #include <zypp/base/IOStream.h>
11 #include <zypp/base/PtrTypes.h>
12
13 #include <zypp/CapFactory.h>
14 #include <zypp/CapSet.h>
15
16 using namespace std;
17 using namespace zypp;
18
19 // work around flaw in y2logview
20 template<class _Tp>
21   void printOnHack( const _Tp & obj )
22   {
23     MIL << obj << endl;
24   };
25
26 ///////////////////////////////////////////////////////////////////
27 // Just for the stats
28 struct Measure
29 {
30   time_t _begin;
31   Measure()
32   : _begin( time(NULL) )
33   {
34     USR << "START MEASURE..." << endl;
35   }
36   ~Measure()
37   {
38     USR << "DURATION: " << (time(NULL)-_begin) << " sec." << endl;
39   }
40 };
41
42 ///////////////////////////////////////////////////////////////////
43 // Print stream status
44 ostream & operator<<( ostream & str, const istream & obj ) {
45   return str
46   << (obj.good() ? 'g' : '_')
47   << (obj.eof()  ? 'e' : '_')
48   << (obj.fail() ? 'F' : '_')
49   << (obj.bad()  ? 'B' : '_');
50 }
51
52 ///////////////////////////////////////////////////////////////////
53 // Fits forEachLine. A simple 'do' function
54 void collect( const std::string & linre_r )
55 {
56   DBG << linre_r << endl;
57 }
58 ///////////////////////////////////////////////////////////////////
59 // Fits forEachLine. A simple 'do' functor counting lines as base.
60 /*
61  Line processing is prepared by providing 'virtual void doConsume(std::string)'.
62  That's what a derived Collector will overload.
63  */
64 struct Collector : public std::unary_function<const std::string &, bool>
65 {
66   unsigned _lineNo;
67   Collector()
68   : _lineNo( 0 )
69   {}
70   virtual ~Collector()
71   {}
72   virtual void doConsume( const std::string & line_r )
73   {}
74   bool operator()( const std::string & line_r )
75   {
76     ++_lineNo;
77     if ( ! (_lineNo % 10000) )
78       DBG << "Got " << _lineNo << " lines..." << endl;
79     doConsume( line_r );
80     return true;
81   }
82 };
83 ///////////////////////////////////////////////////////////////////
84 // Fits forEachLine. An impatient collector ;)
85 struct ImpatientCollector : public Collector
86 {
87   virtual void doConsume( const std::string & line_r )
88   {
89     if ( _lineNo == 1234 )
90       ZYPP_THROW( Exception("takes to long") );
91   }
92 };
93 ///////////////////////////////////////////////////////////////////
94 // Fits forEachLine. Almost usefull collector.
95 /*
96  Note that it's still a functor 'void operator()( const std::string & )'.
97
98  On every invocation the string is parsed into a Capability, and the
99  Capability is stored in a CapSet.
100
101  Exceptions building the Capability are caught and collected in a
102  Failure list. It's a matter of taste whether to immediately abort,
103  or to parse to the end check for collected errors then. Room for
104  improvement.
105
106  see enhacedCollectorUsage().
107 */
108 struct EnhacedCollector : public Collector
109 {
110   // Stores line number, original string and Exception
111   struct Failure
112   {
113     unsigned _lineNo;
114     std::string _line;
115     Exception _excpt;
116     Failure( unsigned lineNo_r,
117              const std::string & line_r, const Exception & excpt_r )
118     : _lineNo( lineNo_r ), _line( line_r ), _excpt( excpt_r )
119     {}
120   };
121
122   typedef std::list<Failure> FailedList;
123
124   CapFactory  _factory;
125   unsigned    _capLines;
126   CapSet      _caps;
127   FailedList  _failures;
128
129
130   EnhacedCollector()
131   : _capLines( 0 )
132   {}
133
134   void makeCap( const string & line_r )
135   {
136     ++_capLines; // count attempts
137     try
138       {
139         // bulid Package deps.
140         _caps.insert( _factory.parse( ResTraits<Package>::kind, line_r ) );
141       }
142     catch( Exception & excpt_r )
143       {
144         _failures.push_back( Failure(_lineNo, line_r, excpt_r) );
145       }
146   }
147
148   virtual void doConsume( const std::string & line_r )
149   {
150     makeCap( line_r );
151   }
152 };
153
154 // Print a Failure
155 ostream & operator<<( ostream & str, const EnhacedCollector::Failure & obj )
156 {
157   return str << str::form( "[%u] \"%s\" ==> %s",
158                            obj._lineNo,
159                            obj._line.c_str(),
160                            obj._excpt.asString().c_str() );
161 }
162
163 // Print EnhacedCollector stats
164 ostream & operator<<( ostream & str, const EnhacedCollector & obj )
165 {
166   str << "Lines parsed : " << obj._lineNo << endl;
167   str << "Cap lines    : " << obj._capLines << endl;
168   str << "Capabilites  : " << obj._caps.size() << endl;
169   str << "Parse errors : " << obj._failures.size() << endl;
170   if ( obj._failures.size() )
171     {
172       copy( obj._failures.begin(), obj._failures.end(),
173             ostream_iterator<EnhacedCollector::Failure>(ERR,"\n") );
174       //-something-we-should-not-do-unless-....---------^^^
175     }
176   return str;
177 }
178
179 ///////////////////////////////////////////////////////////////////
180 // Fits forEachLine.
181 /*
182  Within a packages file, not every line defines a Capability. So
183  EnhacedCollector is refined to turn Capability collection on and
184  off, as appropriate. A dumb version simply storing all Capabilities
185  defined somewhere in the packages file.
186 */
187 struct PackageParseCollector : public EnhacedCollector
188 {
189   static std::string _rxStrDeps;
190   static str::regex  _rxDepOn;
191   static str::regex  _rxDepOff;
192
193   str::smatch _what;
194   bool        _consume;
195
196   PackageParseCollector()
197   : _consume( false )
198   {}
199
200   bool matches( const string & line_r, const str::regex & rx_r )
201   {
202     return str::regex_match( line_r.begin(), line_r.end(), rx_r );
203   }
204
205   virtual void doConsume( const std::string & line_r )
206   {
207     if ( _consume )
208       {
209         if ( matches( line_r, _rxDepOff ) )
210           {
211             _consume = false;
212           }
213         else
214           {
215             EnhacedCollector::doConsume( line_r );
216           }
217       }
218     else if ( matches( line_r, _rxDepOn ) )
219       {
220         _consume = true;
221       }
222   }
223 };
224
225 std::string PackageParseCollector::_rxStrDeps( "(Req|Prq|Prv|Con|Obs)" );
226 str::regex  PackageParseCollector::_rxDepOn ( str::form( "\\+%s:", _rxStrDeps.c_str() ) );
227 str::regex  PackageParseCollector::_rxDepOff( str::form( "-%s:", _rxStrDeps.c_str() ) );
228
229 /******************************************************************
230 **
231 **      FUNCTION NAME : enhacedCollectorUsage
232 **      FUNCTION TYPE :
233 */
234 void enhacedCollectorUsage()
235 {
236   // EnhacedCollector: Simply collect strings which are expected to
237   // be Capabilities. Error handling is delayed by collecting failures.
238   EnhacedCollector collector;
239   collector( "" );
240   collector( "foo baa kaa" );
241   collector( "/bin/sh" );
242   collector( "/bin/sh" );
243   collector( "/bin/sh" );
244   collector( "/bin/sh" );
245
246   MIL << collector << endl;
247   MIL << "Capabilities found:" << endl;
248   for_each( collector._caps.begin(), collector._caps.end(),
249             printOnHack<Capability> );
250 }
251
252 /******************************************************************
253 **
254 **      FUNCTION NAME : main
255 **      FUNCTION TYPE : int
256 */
257 int main( int argc, char * argv[] )
258 {
259   --argc;
260   ++argv;
261   if ( ! argc )
262     {
263       cerr << "Usage: Example.createCapabilities <packages file>" << endl;
264       return 1;
265     }
266   string file( argv[0] );
267
268   INT << "===[START]==========================================" << endl;
269
270   // dump PackageParseCollector: open the file, and build Capabilities
271   // from each appropriate line. Collecting failures.
272
273   ifstream str( file.c_str() );
274   (str?DBG:ERR) << file << ": " << str << endl;
275   shared_ptr<Measure> duration( new Measure );
276
277   PackageParseCollector datacollect;
278   try
279     {
280       iostr::forEachLine( str, datacollect );
281     }
282   catch ( Exception & excpt_r )
283     {
284       // Note: Exceptions building a Capability are caught. So this is
285       // something different. Maybe a bored ImpatientCollector.
286       ZYPP_CAUGHT( excpt_r );
287       ERR << "Parse error at line " << datacollect._lineNo << ": " << excpt_r << endl;
288       return 1;
289     }
290
291   duration.reset();
292   DBG << file << ": " << str << endl;
293
294   MIL << datacollect << endl;
295   MIL << "Capabilities found:" << endl;
296   for_each( datacollect._caps.begin(), datacollect._caps.end(),
297             printOnHack<Capability> );
298
299   INT << "===[END]============================================" << endl;
300   return 0;
301 }