1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/sat/LookupAttr.cc
15 #include "zypp/base/LogTools.h"
16 #include "zypp/base/String.h"
18 #include "zypp/sat/detail/PoolImpl.h"
20 #include "zypp/sat/Pool.h"
21 #include "zypp/sat/LookupAttr.h"
22 #include "zypp/base/StrMatcher.h"
24 #include "zypp/CheckSum.h"
28 ///////////////////////////////////////////////////////////////////
30 { /////////////////////////////////////////////////////////////////
31 ///////////////////////////////////////////////////////////////////
33 { /////////////////////////////////////////////////////////////////
35 using detail::noSolvableId;
37 ///////////////////////////////////////////////////////////////////
39 // CLASS NAME : LookupAttr::Impl
41 ///////////////////////////////////////////////////////////////////
43 * LookupAttr implememtation.
45 * Repository and Solvable must not be set at the same time!
47 * \note When looking in pool or repo, \ref Solvable \c _solv is
48 * somewhat abused to store eiter \c Id \c 0 or \c SOLVID_META, which
49 * indicates whether the dataiterator should look into solvable or
50 * repository metadata. Remember that all \ref Solvables with an
51 * \e invalid \c Id, are treated as <tt>== Solvable::noSolvable</tt>,
52 * and in a boolean context evaluate to \c false. Thus \c noSolvable
53 * may have different \c Ids.
55 class LookupAttr::Impl
59 : _parent( SolvAttr::noAttr )
61 Impl( SolvAttr attr_r, Location loc_r )
62 : _attr( attr_r ), _parent( attr_r.parent() ), _solv( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId )
64 Impl( SolvAttr attr_r, Repository repo_r, Location loc_r )
65 : _attr( attr_r ), _parent( attr_r.parent() ), _repo( repo_r ), _solv( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId )
67 Impl( SolvAttr attr_r, Solvable solv_r )
68 : _attr( attr_r ), _parent( attr_r.parent() ), _solv( solv_r )
75 void setAttr( SolvAttr attr_r )
78 SolvAttr p( _attr.parent() );
79 if ( p != SolvAttr::noAttr )
83 const StrMatcher & strMatcher() const
84 { return _strMatcher; }
86 void setStrMatcher( const StrMatcher & matcher_r )
89 _strMatcher = matcher_r;
94 { return ! (_repo || _solv); }
96 void setPool( Location loc_r )
98 _repo = Repository::noRepository;
99 _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId );
102 Repository repo() const
105 void setRepo( Repository repo_r, Location loc_r )
108 _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId );
111 Solvable solvable() const
114 void setSolvable( Solvable solv_r )
116 _repo = Repository::noRepository;
120 SolvAttr parent() const
123 void setParent( SolvAttr attr_r )
124 { _parent = attr_r; }
127 LookupAttr::iterator begin() const
129 if ( _attr == SolvAttr::noAttr || sat::Pool::instance().reposEmpty() )
132 detail::RepoIdType whichRepo = detail::noRepoId; // all repos
134 whichRepo = _solv.repository().id();
136 whichRepo = _repo.id();
138 detail::DIWrap dip( whichRepo, _solv.id(), _attr.id(), _strMatcher.searchstring(), _strMatcher.flags().get() );
139 if ( _parent != SolvAttr::noAttr )
140 ::dataiterator_prepend_keyname( dip.get(), _parent.id() );
142 return iterator( dip ); // iterator takes over ownership!
145 LookupAttr::iterator end() const
146 { return iterator(); }
153 StrMatcher _strMatcher;
156 friend Impl * rwcowClone<Impl>( const Impl * rhs );
157 /** clone for RWCOW_pointer */
159 { return new Impl( *this ); }
162 ///////////////////////////////////////////////////////////////////
164 // CLASS NAME : LookupAttr
166 ///////////////////////////////////////////////////////////////////
168 LookupAttr::LookupAttr()
172 LookupAttr::LookupAttr( SolvAttr attr_r, Location loc_r )
173 : _pimpl( new Impl( attr_r, loc_r ) )
175 LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Location loc_r )
176 : _pimpl( new Impl( attr_r, loc_r ) )
177 { _pimpl->setParent( parent_r ); }
179 LookupAttr::LookupAttr( SolvAttr attr_r, Repository repo_r, Location loc_r )
180 : _pimpl( new Impl( attr_r, repo_r, loc_r ) )
182 LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Repository repo_r, Location loc_r )
183 : _pimpl( new Impl( attr_r, repo_r, loc_r ) )
184 { _pimpl->setParent( parent_r ); }
186 LookupAttr::LookupAttr( SolvAttr attr_r, Solvable solv_r )
187 : _pimpl( new Impl( attr_r, solv_r ) )
189 LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Solvable solv_r )
190 : _pimpl( new Impl( attr_r, solv_r ) )
191 { _pimpl->setParent( parent_r ); }
194 ///////////////////////////////////////////////////////////////////
196 SolvAttr LookupAttr::attr() const
197 { return _pimpl->attr(); }
199 void LookupAttr::setAttr( SolvAttr attr_r )
200 { _pimpl->setAttr( attr_r ); }
202 const StrMatcher & LookupAttr::strMatcher() const
203 { return _pimpl->strMatcher(); }
205 void LookupAttr::setStrMatcher( const StrMatcher & matcher_r )
206 { _pimpl->setStrMatcher( matcher_r ); }
208 ///////////////////////////////////////////////////////////////////
210 bool LookupAttr::pool() const
211 { return _pimpl->pool(); }
213 void LookupAttr::setPool( Location loc_r )
214 { _pimpl->setPool( loc_r ); }
216 Repository LookupAttr::repo() const
217 { return _pimpl->repo(); }
219 void LookupAttr::setRepo( Repository repo_r, Location loc_r )
220 { _pimpl->setRepo( repo_r, loc_r ); }
222 Solvable LookupAttr::solvable() const
223 { return _pimpl->solvable(); }
225 void LookupAttr::setSolvable( Solvable solv_r )
226 { _pimpl->setSolvable( solv_r ); }
228 SolvAttr LookupAttr::parent() const
229 { return _pimpl->parent(); }
231 void LookupAttr::setParent( SolvAttr attr_r )
232 { _pimpl->setParent( attr_r ); }
234 ///////////////////////////////////////////////////////////////////
236 LookupAttr::iterator LookupAttr::begin() const
237 { return _pimpl->begin(); }
239 LookupAttr::iterator LookupAttr::end() const
240 { return _pimpl->end(); }
242 bool LookupAttr::empty() const
243 { return begin() == end(); }
245 LookupAttr::size_type LookupAttr::size() const
248 for_( it, begin(), end() )
253 ///////////////////////////////////////////////////////////////////
255 std::ostream & operator<<( std::ostream & str, const LookupAttr & obj )
257 if ( obj.attr() == SolvAttr::noAttr )
258 return str << "search nothing";
261 str << "seach " << obj.attr() << " in ";
263 str << "seach ALL in ";
265 if ( obj.solvable() )
266 return str << obj.solvable();
268 return str << obj.repo();
269 return str << "pool";
272 std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj )
274 return dumpRange( str << obj, obj.begin(), obj.end() );
277 ///////////////////////////////////////////////////////////////////
279 // CLASS NAME : LookupRepoAttr
281 ///////////////////////////////////////////////////////////////////
283 LookupRepoAttr::LookupRepoAttr( SolvAttr attr_r, Repository repo_r )
284 : LookupAttr( attr_r, repo_r, REPO_ATTR )
287 void LookupRepoAttr::setRepo( Repository repo_r )
288 { LookupAttr::setRepo( repo_r, REPO_ATTR ); }
290 ///////////////////////////////////////////////////////////////////
292 // CLASS NAME : detail::DIWrap
294 ///////////////////////////////////////////////////////////////////
298 DIWrap::DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
299 const std::string & mstring_r, int flags_r )
300 : _dip( new ::Dataiterator )
301 , _mstring( mstring_r )
303 ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r,
304 _mstring.empty() ? 0 : _mstring.c_str(), flags_r );
307 DIWrap::DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
308 const char * mstring_r, int flags_r )
309 : _dip( new ::Dataiterator )
310 , _mstring( mstring_r ? mstring_r : "" )
312 ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r,
313 _mstring.empty() ? 0 : _mstring.c_str(), flags_r );
316 DIWrap::DIWrap( const DIWrap & rhs )
318 , _mstring( rhs._mstring )
322 _dip = new ::Dataiterator;
323 ::dataiterator_init_clone( _dip, rhs._dip );
324 ::dataiterator_strdup( _dip );
332 ::dataiterator_free( _dip );
337 std::ostream & operator<<( std::ostream & str, const DIWrap & obj )
338 { return str << obj.get(); }
341 ///////////////////////////////////////////////////////////////////
343 // CLASS NAME : LookupAttr::iterator
345 ///////////////////////////////////////////////////////////////////
347 ///////////////////////////////////////////////////////////////////
348 // position and moving
349 ///////////////////////////////////////////////////////////////////
351 Repository LookupAttr::iterator::inRepo() const
352 { return _dip ? Repository( _dip->repo ) : Repository::noRepository; }
354 Solvable LookupAttr::iterator::inSolvable() const
355 { return _dip ? Solvable( _dip->solvid ) : Solvable::noSolvable; }
357 SolvAttr LookupAttr::iterator::inSolvAttr() const
358 { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; }
360 void LookupAttr::iterator::nextSkipSolvAttr()
361 { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); }
363 void LookupAttr::iterator::nextSkipSolvable()
364 { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); }
366 void LookupAttr::iterator::nextSkipRepo()
367 { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); }
369 void LookupAttr::iterator::stayInThisSolvable()
370 { if ( _dip ) { _dip.get()->repoid = -1; _dip.get()->flags |= SEARCH_THISSOLVID; } }
372 void LookupAttr::iterator::stayInThisRepo()
373 { if ( _dip ) { _dip.get()->repoid = -1; } }
375 ///////////////////////////////////////////////////////////////////
376 // attr value type test
377 ///////////////////////////////////////////////////////////////////
379 detail::IdType LookupAttr::iterator::solvAttrType() const
380 { return _dip ? _dip->key->type : detail::noId; }
382 bool LookupAttr::iterator::solvAttrNumeric() const
384 switch ( solvAttrType() )
386 case REPOKEY_TYPE_NUM:
387 case REPOKEY_TYPE_CONSTANT:
394 bool LookupAttr::iterator::solvAttrString() const
396 switch ( solvAttrType() )
398 case REPOKEY_TYPE_ID:
399 case REPOKEY_TYPE_IDARRAY:
400 case REPOKEY_TYPE_CONSTANTID:
401 case REPOKEY_TYPE_STR:
402 case REPOKEY_TYPE_DIRSTRARRAY:
409 bool LookupAttr::iterator::solvAttrIdString() const
411 switch ( solvAttrType() )
413 case REPOKEY_TYPE_ID:
414 case REPOKEY_TYPE_IDARRAY:
415 case REPOKEY_TYPE_CONSTANTID:
422 bool LookupAttr::iterator::solvAttrCheckSum() const
424 switch ( solvAttrType() )
426 case REPOKEY_TYPE_MD5:
427 case REPOKEY_TYPE_SHA1:
428 case REPOKEY_TYPE_SHA256:
435 ///////////////////////////////////////////////////////////////////
438 enum SubType { ST_NONE, // no sub-structure
439 ST_FLEX, // flexarray
440 ST_SUB }; // inside sub-structure
441 SubType subType( const detail::DIWrap & dip )
445 if ( dip.get()->key->type == REPOKEY_TYPE_FLEXARRAY )
447 return dip.get()->kv.parent ? ST_SUB : ST_NONE;
450 ///////////////////////////////////////////////////////////////////
452 bool LookupAttr::iterator::solvAttrSubEntry() const
453 { return subType( _dip ) != ST_NONE; }
455 ///////////////////////////////////////////////////////////////////
456 // Iterate sub-structures.
457 ///////////////////////////////////////////////////////////////////
459 bool LookupAttr::iterator::subEmpty() const
460 { return( subBegin() == subEnd() ); }
462 LookupAttr::size_type LookupAttr::iterator::subSize() const
465 for_( it, subBegin(), subEnd() )
470 LookupAttr::iterator LookupAttr::iterator::subBegin() const
472 SubType subtype( subType( _dip ) );
473 if ( subtype == ST_NONE )
475 // setup the new sub iterator with the remembered position
476 detail::DIWrap dip( 0, 0, 0 );
477 ::dataiterator_clonepos( dip.get(), _dip.get() );
480 case ST_NONE: // not reached
483 ::dataiterator_seek( dip.get(), DI_SEEK_CHILD|DI_SEEK_STAY );
486 ::dataiterator_seek( dip.get(), DI_SEEK_REWIND|DI_SEEK_STAY );
489 return iterator( dip ); // iterator takes over ownership!
492 LookupAttr::iterator LookupAttr::iterator::subEnd() const
497 LookupAttr::iterator LookupAttr::iterator::subFind( SolvAttr attr_r ) const
499 iterator it = subBegin();
500 if ( attr_r != sat::SolvAttr::allAttr )
502 while ( it != subEnd() && it.inSolvAttr() != attr_r )
508 LookupAttr::iterator LookupAttr::iterator::subFind( const C_Str & attrname_r ) const
510 if ( attrname_r.empty() )
513 SubType subtype( subType( _dip ) );
514 if ( subtype == ST_NONE )
517 std::string subattr( inSolvAttr().asString() );
518 if ( subtype == ST_FLEX )
520 // append ":attrname"
522 subattr += attrname_r;
526 // replace "oldname" after ':' with "attrname"
527 std::string::size_type pos( subattr.rfind( ':' ) );
528 if ( pos != std::string::npos )
530 subattr.erase( pos+1 );
531 subattr += attrname_r;
534 subattr = attrname_r; // no ':' so replace all.
536 return subFind( SolvAttr( subattr ) );
539 ///////////////////////////////////////////////////////////////////
540 // attr value retrieval
541 ///////////////////////////////////////////////////////////////////
543 int LookupAttr::iterator::asInt() const
547 switch ( solvAttrType() )
549 case REPOKEY_TYPE_NUM:
550 case REPOKEY_TYPE_CONSTANT:
558 unsigned LookupAttr::iterator::asUnsigned() const
561 unsigned long long LookupAttr::iterator::asUnsignedLL() const
565 switch ( solvAttrType() )
567 case REPOKEY_TYPE_NUM:
568 case REPOKEY_TYPE_CONSTANT:
569 return SOLV_KV_NUM64(&_dip->kv);
576 bool LookupAttr::iterator::asBool() const
580 const char * LookupAttr::iterator::c_str() const
584 switch ( solvAttrType() )
586 case REPOKEY_TYPE_ID:
587 case REPOKEY_TYPE_IDARRAY:
588 case REPOKEY_TYPE_CONSTANTID:
589 if ( _dip->data && _dip->data->localpool )
590 return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id ); // in local pool
592 return IdString( _dip->kv.id ).c_str(); // in global pool
595 case REPOKEY_TYPE_STR:
599 case REPOKEY_TYPE_DIRSTRARRAY:
600 // may or may not be stringified depending on SEARCH_FILES flag
601 return( _dip->flags & SEARCH_FILES
603 : ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str ) );
610 std::string LookupAttr::iterator::asString() const
614 switch ( solvAttrType() )
616 case REPOKEY_TYPE_ID:
617 case REPOKEY_TYPE_IDARRAY:
618 case REPOKEY_TYPE_CONSTANTID:
620 detail::IdType id = ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 );
621 return ISRELDEP(id) ? Capability( id ).asString()
622 : IdString( id ).asString();
626 case REPOKEY_TYPE_STR:
627 case REPOKEY_TYPE_DIRSTRARRAY:
629 const char * ret( c_str() );
630 return ret ? ret : "";
634 case REPOKEY_TYPE_NUM:
635 case REPOKEY_TYPE_CONSTANT:
636 return str::numstring( asInt() );
639 case REPOKEY_TYPE_MD5:
640 case REPOKEY_TYPE_SHA1:
641 case REPOKEY_TYPE_SHA256:
643 return asCheckSum().asString();
647 case REPOKEY_TYPE_FLEXARRAY:
649 std::ostringstream str;
651 for_( it, subBegin(), subEnd() )
653 str << " " << it.inSolvAttr() << " = " << it.asString() << endl;
661 return std::string();
664 IdString LookupAttr::iterator::idStr() const
668 switch ( solvAttrType() )
670 case REPOKEY_TYPE_ID:
671 case REPOKEY_TYPE_IDARRAY:
672 case REPOKEY_TYPE_CONSTANTID:
673 return IdString( ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 ) );
680 CheckSum LookupAttr::iterator::asCheckSum() const
684 switch ( solvAttrType() )
686 case REPOKEY_TYPE_MD5:
687 return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
690 case REPOKEY_TYPE_SHA1:
691 return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
694 case REPOKEY_TYPE_SHA224:
695 return CheckSum::sha224( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
698 case REPOKEY_TYPE_SHA256:
699 return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
702 case REPOKEY_TYPE_SHA384:
703 return CheckSum::sha384( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
706 case REPOKEY_TYPE_SHA512:
707 return CheckSum::sha512( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
714 ///////////////////////////////////////////////////////////////////
715 // internal stuff below
716 ///////////////////////////////////////////////////////////////////
718 LookupAttr::iterator::iterator()
719 : iterator_adaptor_( 0 )
722 LookupAttr::iterator::iterator( const iterator & rhs )
723 : iterator_adaptor_( 0 )
726 base_reference() = _dip.get();
729 LookupAttr::iterator::iterator( detail::DIWrap & dip_r )
730 : iterator_adaptor_( 0 )
732 _dip.swap( dip_r ); // take ownership!
733 base_reference() = _dip.get();
737 LookupAttr::iterator::~iterator()
740 LookupAttr::iterator & LookupAttr::iterator::operator=( const iterator & rhs )
745 base_reference() = _dip.get();
750 ///////////////////////////////////////////////////////////////////
752 bool LookupAttr::iterator::dip_equal( const detail::CDataiterator & lhs, const detail::CDataiterator & rhs ) const
754 // Iterator equal is same position in same container.
755 // Here: same attribute in same solvable.
756 return( lhs.solvid == rhs.solvid && lhs.key->name == rhs.key->name );
759 detail::IdType LookupAttr::iterator::dereference() const
761 return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 )
765 void LookupAttr::iterator::increment()
769 if ( ! ::dataiterator_step( _dip.get() ) )
772 base_reference() = 0;
776 ::dataiterator_strdup( _dip.get() );
781 std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
783 const detail::CDataiterator * dip = obj.get();
785 return str << "EndOfQuery";
787 if ( obj.inSolvable() )
788 str << obj.inSolvable();
789 else if ( obj.inRepo() )
792 str << '<' << obj.inSolvAttr() << (obj.solvAttrSubEntry() ? ">(*" : ">(")
793 << IdString(obj.solvAttrType()) << ") = " << obj.asString();
797 template<> CheckSum LookupAttr::iterator::asType<CheckSum>() const
798 { return asCheckSum(); }
800 /////////////////////////////////////////////////////////////////
802 ///////////////////////////////////////////////////////////////////
803 /////////////////////////////////////////////////////////////////
805 ///////////////////////////////////////////////////////////////////
807 std::ostream & operator<<( std::ostream & str, const zypp::sat::detail::CDataiterator * obj )
809 str << "detail::CDataiterator(";
816 str << "|" << zypp::Repository(obj->repo);
817 str << "|" << zypp::sat::Solvable(obj->solvid);
818 str << "|" << zypp::IdString(obj->key->name);
819 str << "|" << zypp::IdString(obj->key->type);
820 str << "|" << obj->repodataid;
821 str << "|" << obj->repoid;
826 ///////////////////////////////////////////////////////////////////