adjust debug output
[platform/upstream/libzypp.git] / zypp / sat / LookupAttr.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/LookupAttr.cc
10  *
11 */
12 #include <iostream>
13 #include <sstream>
14
15 #include "zypp/base/LogTools.h"
16 #include "zypp/base/String.h"
17
18 #include "zypp/sat/detail/PoolImpl.h"
19
20 #include "zypp/sat/LookupAttr.h"
21 #include "zypp/CheckSum.h"
22
23 using std::endl;
24
25 ///////////////////////////////////////////////////////////////////
26 namespace zypp
27 { /////////////////////////////////////////////////////////////////
28   ///////////////////////////////////////////////////////////////////
29   namespace sat
30   { /////////////////////////////////////////////////////////////////
31
32     LookupAttr::iterator LookupAttr::begin() const
33     {
34       if ( _attr == SolvAttr::noAttr )
35         return iterator();
36
37 #warning Need to call dataiterator_free, use Autodispose instead of scoped_ptr
38       scoped_ptr< ::_Dataiterator> dip( new ::Dataiterator );
39       // needed while LookupAttr::iterator::dip_equal does ::memcmp:
40       ::memset( dip.get(), 0, sizeof(::_Dataiterator) );
41
42       if ( _solv )
43       {
44         ::dataiterator_init( dip.get(), sat::Pool::instance().get(), _solv.repository().id(), _solv.id(), _attr.id(), 0, 0 );
45       }
46       else if ( _repo )
47       {
48         ::dataiterator_init( dip.get(), sat::Pool::instance().get(),              _repo.id(),          0, _attr.id(), 0, 0 );
49       }
50       else if ( ! sat::Pool::instance().reposEmpty() )
51       {
52         ::dataiterator_init( dip.get(), sat::Pool::instance().get(),                       0,          0, _attr.id(), 0, 0 );
53       }
54       else
55         return iterator();
56
57       return iterator( dip ); // iterator takes over ownership!
58     }
59
60     LookupAttr::iterator LookupAttr::end() const
61     {
62       return iterator();
63     }
64
65     bool LookupAttr::empty() const
66     { return begin() == end(); }
67
68     LookupAttr::size_type LookupAttr::size() const
69     {
70       size_type c = 0;
71       for_( it, begin(), end() )
72         ++c;
73       return c;
74     }
75
76     std::ostream & operator<<( std::ostream & str, const LookupAttr & obj )
77     {
78       if ( obj.attr() == SolvAttr::noAttr )
79         return str << "search nothing";
80
81       if ( obj.attr() )
82         str << "seach " << obj.attr() << " in ";
83       else
84         str << "seach ALL in ";
85
86       if ( obj.solvable() )
87         return str << obj.solvable();
88       if ( obj.repo() )
89         return str << obj.repo();
90       return str << "pool";
91     }
92
93     std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj )
94     {
95       return dumpRange( str << obj, obj.begin(), obj.end() );
96     }
97
98     ///////////////////////////////////////////////////////////////////
99     //
100     //  CLASS NAME : LookupAttr::iterator
101     //
102     ///////////////////////////////////////////////////////////////////
103
104     ///////////////////////////////////////////////////////////////////
105     // position and moving
106     ///////////////////////////////////////////////////////////////////
107
108     Repository LookupAttr::iterator::inRepo() const
109     { return _dip ? Repository( _dip->repo ) : Repository::noRepository; }
110
111     Solvable LookupAttr::iterator::inSolvable() const
112     { return _dip ? Solvable( _dip->solvid ) : Solvable::noSolvable; }
113
114     SolvAttr LookupAttr::iterator::inSolvAttr() const
115     { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; }
116
117     void LookupAttr::iterator::nextSkipSolvAttr()
118     { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); }
119
120     void LookupAttr::iterator::nextSkipSolvable()
121     { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); }
122
123     void LookupAttr::iterator::nextSkipRepo()
124     { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); }
125
126     ///////////////////////////////////////////////////////////////////
127     // attr value type test
128     ///////////////////////////////////////////////////////////////////
129
130     detail::IdType LookupAttr::iterator::solvAttrType() const
131     { return _dip ? _dip->key->type : detail::noId; }
132
133     bool LookupAttr::iterator::solvAttrNumeric() const
134     {
135       switch ( solvAttrType() )
136       {
137         case REPOKEY_TYPE_U32:
138         case REPOKEY_TYPE_NUM:
139         case REPOKEY_TYPE_CONSTANT:
140           return true;
141           break;
142       }
143       return false;
144     }
145
146     bool LookupAttr::iterator::solvAttrString() const
147     {
148       switch ( solvAttrType() )
149       {
150         case REPOKEY_TYPE_ID:
151         case REPOKEY_TYPE_IDARRAY:
152         case REPOKEY_TYPE_CONSTANTID:
153         case REPOKEY_TYPE_STR:
154         case REPOKEY_TYPE_DIRSTRARRAY:
155           return true;
156           break;
157       }
158       return false;
159     }
160
161     bool LookupAttr::iterator::solvAttrIdString() const
162     {
163       switch ( solvAttrType() )
164       {
165         case REPOKEY_TYPE_ID:
166         case REPOKEY_TYPE_IDARRAY:
167         case REPOKEY_TYPE_CONSTANTID:
168           return true;
169           break;
170       }
171       return false;
172     }
173
174     bool LookupAttr::iterator::solvAttrCheckSum() const
175     {
176       switch ( solvAttrType() )
177       {
178         case REPOKEY_TYPE_MD5:
179         case REPOKEY_TYPE_SHA1:
180         case REPOKEY_TYPE_SHA256:
181           return true;
182           break;
183       }
184       return false;
185     }
186
187     bool LookupAttr::iterator::solvAttrSubEntry() const
188     {
189       return solvAttrType() == REPOKEY_TYPE_FLEXARRAY;
190     }
191
192     ///////////////////////////////////////////////////////////////////
193     // Iterate sub-structures.
194     ///////////////////////////////////////////////////////////////////
195
196     bool LookupAttr::iterator::subEmpty() const
197     { return( subBegin() == subEnd() ); }
198
199     LookupAttr::size_type LookupAttr::iterator::subSize() const
200     {
201       size_type c = 0;
202       for_( it, subBegin(), subEnd() )
203         ++c;
204       return c;
205     }
206
207     LookupAttr::iterator LookupAttr::iterator::subBegin() const
208     {
209       if ( ! solvAttrSubEntry() )
210         return subEnd();
211
212       // remember this position
213       ::dataiterator_setpos( _dip.get() );
214
215       // setup the new sub iterator
216       scoped_ptr< ::_Dataiterator> dip( new ::Dataiterator );
217       // needed while LookupAttr::iterator::dip_equal does ::memcmp:
218       ::memset( dip.get(), 0, sizeof(::_Dataiterator) );
219
220       ::dataiterator_init( dip.get(), sat::Pool::instance().get(), 0, SOLVID_POS, 0, 0, 0 );
221
222       return iterator( dip ); // iterator takes over ownership!
223     }
224
225     LookupAttr::iterator LookupAttr::iterator::subEnd() const
226     {
227       return iterator();
228     }
229
230     LookupAttr::iterator LookupAttr::iterator::subFind( SolvAttr attr_r ) const
231     {
232       iterator it = subBegin();
233       if ( attr_r != sat::SolvAttr::allAttr )
234       {
235         while ( it != subEnd() && it.inSolvAttr() != attr_r )
236           ++it;
237       }
238       return it;
239     }
240
241     LookupAttr::iterator LookupAttr::iterator::subFind( const C_Str & attrname_r ) const
242     {
243       if ( attrname_r.empty() )
244         return subBegin();
245
246       std::string subattr( inSolvAttr().asString() );
247       subattr += ":";
248       subattr += attrname_r;
249       return subFind( SolvAttr( subattr ) );
250     }
251
252     ///////////////////////////////////////////////////////////////////
253     // attr value retrieval
254     ///////////////////////////////////////////////////////////////////
255
256     int LookupAttr::iterator::asInt() const
257     {
258       if ( _dip )
259       {
260         switch ( solvAttrType() )
261         {
262           case REPOKEY_TYPE_U32:
263           case REPOKEY_TYPE_NUM:
264           case REPOKEY_TYPE_CONSTANT:
265             return _dip->kv.num;
266             break;
267         }
268       }
269       return 0;
270     }
271
272     unsigned LookupAttr::iterator::asUnsigned() const
273     { return asInt(); }
274
275     bool LookupAttr::iterator::asBool() const
276     { return asInt(); }
277
278
279     const char * LookupAttr::iterator::c_str() const
280     {
281       if ( _dip )
282       {
283         switch ( solvAttrType() )
284         {
285           case REPOKEY_TYPE_ID:
286           case REPOKEY_TYPE_IDARRAY:
287           case REPOKEY_TYPE_CONSTANTID:
288             if ( _dip->data && _dip->data->localpool )
289               return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id ); // in local pool
290             else
291               return IdString( _dip->kv.id ).c_str(); // in global pool
292             break;
293
294           case REPOKEY_TYPE_STR:
295             return _dip->kv.str;
296             break;
297
298           case REPOKEY_TYPE_DIRSTRARRAY:
299             return ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str );
300             break;
301         }
302       }
303       return 0;
304     }
305
306     std::string LookupAttr::iterator::asString() const
307     {
308       if ( _dip )
309       {
310         switch ( solvAttrType() )
311         {
312           case REPOKEY_TYPE_ID:
313           case REPOKEY_TYPE_IDARRAY:
314           case REPOKEY_TYPE_CONSTANTID:
315           case REPOKEY_TYPE_STR:
316           case REPOKEY_TYPE_DIRSTRARRAY:
317             {
318               const char * ret( c_str() );
319               return ret ? ret : "";
320             }
321             break;
322
323           case REPOKEY_TYPE_U32:
324           case REPOKEY_TYPE_NUM:
325           case REPOKEY_TYPE_CONSTANT:
326             return str::numstring( asInt() );
327             break;
328
329           case REPOKEY_TYPE_MD5:
330           case REPOKEY_TYPE_SHA1:
331           case REPOKEY_TYPE_SHA256:
332             {
333               return asCheckSum().asString();
334             }
335             break;
336
337           case REPOKEY_TYPE_FLEXARRAY:
338             {
339               std::ostringstream str;
340               str << "{" << endl;
341               for_( it, subBegin(), subEnd() )
342               {
343                 str << "  " << it.inSolvAttr() << " = " << it.asString() << endl;
344               }
345               str << "}" << endl;
346              return str.str();
347             }
348             break;
349         }
350       }
351       return std::string();
352     }
353
354     IdString LookupAttr::iterator::idStr() const
355     {
356       if ( _dip )
357       {
358         switch ( solvAttrType() )
359         {
360           case REPOKEY_TYPE_ID:
361           case REPOKEY_TYPE_IDARRAY:
362           case REPOKEY_TYPE_CONSTANTID:
363             return IdString( ::repodata_globalize_id( _dip->data, _dip->kv.id ) );
364             break;
365         }
366       }
367       return IdString();
368     }
369
370     CheckSum LookupAttr::iterator::asCheckSum() const
371     {
372       if ( _dip )
373       {
374         switch ( solvAttrType() )
375         {
376           case REPOKEY_TYPE_MD5:
377             return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
378             break;
379
380           case REPOKEY_TYPE_SHA1:
381             return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
382             break;
383
384           case REPOKEY_TYPE_SHA256:
385             return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
386             break;
387         }
388       }
389       return CheckSum();
390     }
391
392     ///////////////////////////////////////////////////////////////////
393     // internal stuff below
394     ///////////////////////////////////////////////////////////////////
395
396     LookupAttr::iterator::~iterator()
397     {}
398
399     LookupAttr::iterator::iterator()
400     : iterator_adaptor_( 0 )
401     {}
402
403     LookupAttr::iterator::iterator( const iterator & rhs )
404     : iterator_adaptor_( cloneFrom( rhs.base() ) )
405     , _dip( base() )
406     {}
407
408     LookupAttr::iterator & LookupAttr::iterator::operator=( const iterator & rhs )
409     {
410       if ( &rhs != this )
411       {
412         _dip.reset( cloneFrom( rhs.base() ) );
413         base_reference() = _dip.get();
414       }
415       return *this;
416     }
417
418     LookupAttr::iterator::iterator( scoped_ptr< ::_Dataiterator> & dip_r )
419     : iterator_adaptor_( dip_r.get() )
420     {
421       _dip.swap( dip_r ); // take ownership!
422       increment();
423     }
424
425     ///////////////////////////////////////////////////////////////////
426
427     ::_Dataiterator * LookupAttr::iterator::cloneFrom( const ::_Dataiterator * rhs )
428     {
429       if ( ! rhs )
430         return 0;
431       ::_Dataiterator * ret( new ::_Dataiterator );
432       *ret = *rhs;
433       return ret;
434     }
435
436     bool LookupAttr::iterator::dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const
437     {
438       // requires ::memset in LookupAttr::begin
439       return ::memcmp( &lhs, &rhs, sizeof(::_Dataiterator) ) == 0;
440     }
441
442     detail::IdType LookupAttr::iterator::dereference() const
443     {
444       return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id )
445                   : detail::noId;
446     }
447
448     void LookupAttr::iterator::increment()
449     {
450       if ( _dip && ! ::dataiterator_step( _dip.get() ) )
451       {
452         _dip.reset();
453         base_reference() = 0;
454       }
455     }
456
457     std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
458     {
459       const ::_Dataiterator * dip = obj.get();
460       if ( ! dip )
461         return str << "EndOfQuery";
462
463       if ( obj.inSolvable() )
464         str << obj.inSolvable();
465       else if ( obj.inRepo() )
466         str << obj.inRepo();
467
468       str << '<' << obj.inSolvAttr()
469           << ">(" <<  IdString(obj.solvAttrType()) << ") = " << obj.asString();
470       return str;
471     }
472
473     /////////////////////////////////////////////////////////////////
474   } // namespace sat
475   ///////////////////////////////////////////////////////////////////
476   /////////////////////////////////////////////////////////////////
477 } // namespace zypp
478 ///////////////////////////////////////////////////////////////////
479
480 std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj )
481 {
482   str << "::_Dataiterator(";
483   if ( ! obj )
484   {
485     str << "NULL";
486   }
487   else
488   {
489     str << "|" << zypp::Repository(obj->repo);
490     str << "|" << zypp::sat::Solvable(obj->solvid);
491     str << "|" << zypp::IdString(obj->key->name);
492     str << "|" << zypp::IdString(obj->key->type);
493     str << "|" << obj->repodataid;
494     str << "|" << obj->repoid;
495   }
496   return str << ")";
497 }
498
499 ///////////////////////////////////////////////////////////////////