Adapt to satsolvers big solv data change.
[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 <cstring>
13 #include <iostream>
14 #include <sstream>
15
16 #include "zypp/base/LogTools.h"
17 #include "zypp/base/String.h"
18
19 #include "zypp/sat/detail/PoolImpl.h"
20
21 #include "zypp/sat/LookupAttr.h"
22 #include "zypp/CheckSum.h"
23
24 using std::endl;
25
26 ///////////////////////////////////////////////////////////////////
27 namespace zypp
28 { /////////////////////////////////////////////////////////////////
29   ///////////////////////////////////////////////////////////////////
30   namespace sat
31   { /////////////////////////////////////////////////////////////////
32
33     LookupAttr::iterator LookupAttr::begin() const
34     {
35       if ( _attr == SolvAttr::noAttr )
36         return iterator();
37
38 #warning Need to call dataiterator_free
39       scoped_ptr< ::_Dataiterator> dip( new ::Dataiterator );
40       // needed while LookupAttr::iterator::dip_equal does ::memcmp:
41       ::memset( dip.get(), 0, sizeof(::_Dataiterator) );
42       bool chain = false;
43
44       if ( _solv )
45         ::dataiterator_init( dip.get(), _solv.repository().id(), _solv.id(), _attr.id(), 0, 0 );
46       else if ( _repo )
47         ::dataiterator_init( dip.get(), _repo.id(), 0, _attr.id(), 0, 0 );
48       else if ( ! sat::Pool::instance().reposEmpty() )
49       {
50         ::dataiterator_init( dip.get(), sat::Pool::instance().reposBegin()->id(), 0, _attr.id(), 0, 0 );
51         chain = true;
52       }
53       else
54         return iterator();
55
56       return iterator( dip, chain ); // iterator takes over ownership!
57     }
58
59     LookupAttr::iterator LookupAttr::end() const
60     {
61       return iterator();
62     }
63
64     bool LookupAttr::empty() const
65     { return begin() == end(); }
66
67     LookupAttr::size_type LookupAttr::size() const
68     {
69       size_type c = 0;
70       for_( it, begin(), end() )
71         ++c;
72       return c;
73     }
74
75     std::ostream & operator<<( std::ostream & str, const LookupAttr & obj )
76     {
77       if ( obj.attr() == SolvAttr::noAttr )
78         return str << "search nothing";
79
80       if ( obj.attr() )
81         str << "seach " << obj.attr() << " in ";
82       else
83         str << "seach ALL in ";
84
85       if ( obj.solvable() )
86         return str << obj.solvable();
87       if ( obj.repo() )
88         return str << obj.repo();
89       return str << "pool";
90     }
91
92     std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj )
93     {
94       return dumpRange( str << obj, obj.begin(), obj.end() );
95     }
96
97     ///////////////////////////////////////////////////////////////////
98     //
99     //  CLASS NAME : LookupAttr::iterator
100     //
101     ///////////////////////////////////////////////////////////////////
102
103     ///////////////////////////////////////////////////////////////////
104     // position and moving
105     ///////////////////////////////////////////////////////////////////
106
107     Repository LookupAttr::iterator::inRepo() const
108     { return _dip ? Repository( _dip->repo ) : Repository::noRepository; }
109
110     Solvable LookupAttr::iterator::inSolvable() const
111     { return _dip ? Solvable( _dip->entry ) : Solvable::noSolvable; }
112
113     SolvAttr LookupAttr::iterator::inSolvAttr() const
114     { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; }
115
116     void LookupAttr::iterator::nextSkipSolvAttr()
117     { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); }
118
119     void LookupAttr::iterator::nextSkipSolvable()
120     { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); }
121
122     void LookupAttr::iterator::nextSkipRepo()
123     { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); }
124
125     ///////////////////////////////////////////////////////////////////
126     // attr value type test
127     ///////////////////////////////////////////////////////////////////
128
129     detail::IdType LookupAttr::iterator::solvAttrType() const
130     { return _dip ? _dip->key->type : detail::noId; }
131
132     bool LookupAttr::iterator::solvAttrNumeric() const
133     {
134       switch ( solvAttrType() )
135       {
136         case REPOKEY_TYPE_U32:
137         case REPOKEY_TYPE_NUM:
138         case REPOKEY_TYPE_CONSTANT:
139           return true;
140           break;
141       }
142       return false;
143     }
144
145     bool LookupAttr::iterator::solvAttrString() const
146     {
147       switch ( solvAttrType() )
148       {
149         case REPOKEY_TYPE_ID:
150         case REPOKEY_TYPE_IDARRAY:
151         case REPOKEY_TYPE_CONSTANTID:
152         case REPOKEY_TYPE_STR:
153         case REPOKEY_TYPE_DIRSTRARRAY:
154           return true;
155           break;
156       }
157       return false;
158     }
159
160     bool LookupAttr::iterator::solvAttrIdString() const
161     {
162       switch ( solvAttrType() )
163       {
164         case REPOKEY_TYPE_ID:
165         case REPOKEY_TYPE_IDARRAY:
166         case REPOKEY_TYPE_CONSTANTID:
167           return true;
168           break;
169       }
170       return false;
171     }
172
173     bool LookupAttr::iterator::solvAttrCheckSum() const
174     {
175       switch ( solvAttrType() )
176       {
177         case REPOKEY_TYPE_MD5:
178         case REPOKEY_TYPE_SHA1:
179         case REPOKEY_TYPE_SHA256:
180           return true;
181           break;
182       }
183       return false;
184     }
185
186     ///////////////////////////////////////////////////////////////////
187     // attr value retrieval
188     ///////////////////////////////////////////////////////////////////
189
190     int LookupAttr::iterator::asInt() const
191     {
192       if ( _dip )
193       {
194         switch ( solvAttrType() )
195         {
196           case REPOKEY_TYPE_U32:
197           case REPOKEY_TYPE_NUM:
198           case REPOKEY_TYPE_CONSTANT:
199             return _dip->kv.num;
200             break;
201         }
202       }
203       return 0;
204     }
205
206     unsigned LookupAttr::iterator::asUnsigned() const
207     { return asInt(); }
208
209     bool LookupAttr::iterator::asBool() const
210     { return asInt(); }
211
212
213     const char * LookupAttr::iterator::c_str() const
214     {
215       if ( _dip )
216       {
217         switch ( solvAttrType() )
218         {
219           case REPOKEY_TYPE_ID:
220           case REPOKEY_TYPE_IDARRAY:
221           case REPOKEY_TYPE_CONSTANTID:
222             if ( _dip->data && _dip->data->localpool )
223               return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id ); // in local pool
224             else
225               return IdString( _dip->kv.id ).c_str(); // in global pool
226             break;
227
228           case REPOKEY_TYPE_STR:
229             return _dip->kv.str;
230             break;
231
232           case REPOKEY_TYPE_DIRSTRARRAY:
233             return ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str );
234             break;
235         }
236       }
237       return 0;
238     }
239
240     std::string LookupAttr::iterator::asString() const
241     {
242       if ( _dip )
243       {
244         switch ( solvAttrType() )
245         {
246           case REPOKEY_TYPE_ID:
247           case REPOKEY_TYPE_IDARRAY:
248           case REPOKEY_TYPE_CONSTANTID:
249           case REPOKEY_TYPE_STR:
250           case REPOKEY_TYPE_DIRSTRARRAY:
251           {
252             const char * ret( c_str() );
253             return ret ? ret : "";
254           }
255           break;
256
257           case REPOKEY_TYPE_U32:
258           case REPOKEY_TYPE_NUM:
259           case REPOKEY_TYPE_CONSTANT:
260             return str::numstring( asInt() );
261             break;
262
263           case REPOKEY_TYPE_MD5:
264           case REPOKEY_TYPE_SHA1:
265           case REPOKEY_TYPE_SHA256:
266           {
267             std::ostringstream str;
268             str << asCheckSum();
269             return str.str();
270           }
271           break;
272         }
273       }
274       return std::string();
275     }
276
277     IdString LookupAttr::iterator::idStr() const
278     {
279       if ( _dip )
280       {
281         switch ( solvAttrType() )
282         {
283           case REPOKEY_TYPE_ID:
284           case REPOKEY_TYPE_IDARRAY:
285           case REPOKEY_TYPE_CONSTANTID:
286             return IdString( ::repodata_globalize_id( _dip->data, _dip->kv.id ) );
287             break;
288         }
289       }
290       return IdString();
291     }
292
293     CheckSum LookupAttr::iterator::asCheckSum() const
294     {
295       if ( _dip )
296       {
297         switch ( solvAttrType() )
298         {
299           case REPOKEY_TYPE_MD5:
300             return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
301             break;
302
303           case REPOKEY_TYPE_SHA1:
304             return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
305             break;
306
307           case REPOKEY_TYPE_SHA256:
308             return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
309             break;
310         }
311       }
312       return CheckSum();
313     }
314
315     ///////////////////////////////////////////////////////////////////
316     // internal stuff below
317     ///////////////////////////////////////////////////////////////////
318
319     LookupAttr::iterator::~iterator()
320     {}
321
322     LookupAttr::iterator::iterator()
323     : iterator_adaptor_( 0 )
324     {}
325
326     LookupAttr::iterator::iterator( const iterator & rhs )
327     : iterator_adaptor_( cloneFrom( rhs.base() ) )
328     , _dip( base() )
329     , _chainRepos(rhs._chainRepos)
330     {}
331
332     LookupAttr::iterator & LookupAttr::iterator::operator=( const iterator & rhs )
333     {
334       if ( &rhs != this )
335       {
336         _dip.reset( cloneFrom( rhs.base() ) );
337         base_reference() = _dip.get();
338         _chainRepos = rhs._chainRepos;
339       }
340       return *this;
341     }
342
343     LookupAttr::iterator::iterator( scoped_ptr< ::_Dataiterator> & dip_r, bool chain_r )
344     : iterator_adaptor_( dip_r.get() )
345     , _chainRepos( chain_r )
346     {
347       _dip.swap( dip_r ); // take ownership!
348       increment();
349     }
350
351     ///////////////////////////////////////////////////////////////////
352
353     ::_Dataiterator * LookupAttr::iterator::cloneFrom( const ::_Dataiterator * rhs )
354     {
355       if ( ! rhs )
356         return 0;
357       ::_Dataiterator * ret( new ::_Dataiterator );
358       *ret = *rhs;
359       return ret;
360     }
361
362     bool LookupAttr::iterator::dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const
363     {
364       // requires ::memset in LookupAttr::begin
365       return ::memcmp( &lhs, &rhs, sizeof(::_Dataiterator) ) == 0;
366     }
367
368     detail::IdType LookupAttr::iterator::dereference() const
369     {
370       return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id )
371                   : detail::noId;
372     }
373
374     void LookupAttr::iterator::increment()
375     {
376       if ( _dip && ! ::dataiterator_step( _dip.get() ) )
377       {
378         bool haveNext = false;
379         if ( _chainRepos )
380         {
381           Repository nextRepo( inRepo().nextInPool() );
382           if ( nextRepo )
383           {
384             ::dataiterator_jump_to_repo( _dip.get(), nextRepo.get() );
385             haveNext = ::dataiterator_step( _dip.get() );
386           }
387         }
388         if ( ! haveNext )
389         {
390           _dip.reset();
391           base_reference() = 0;
392         }
393       }
394     }
395
396     std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
397     {
398       const ::_Dataiterator * dip = obj.get();
399       if ( ! dip )
400         return str << "EndOfQuery";
401
402       if ( obj.inSolvable() )
403         str << obj.inSolvable();
404       else if ( obj.inRepo() )
405         str << obj.inRepo();
406
407       str << '<' << obj.inSolvAttr()
408           << ">(" <<  obj.solvAttrType() << ") = " << obj.asString();
409       return str;
410     }
411
412     /////////////////////////////////////////////////////////////////
413   } // namespace sat
414   ///////////////////////////////////////////////////////////////////
415   /////////////////////////////////////////////////////////////////
416 } // namespace zypp
417 ///////////////////////////////////////////////////////////////////