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