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