00001
00002
00003
00004
00005
00006
00007
00008
00012 #include <iostream>
00013 #include <sstream>
00014
00015 #include "zypp/base/LogTools.h"
00016 #include "zypp/base/String.h"
00017
00018 #include "zypp/sat/detail/PoolImpl.h"
00019
00020 #include "zypp/sat/Pool.h"
00021 #include "zypp/sat/LookupAttr.h"
00022 #include "zypp/sat/AttrMatcher.h"
00023
00024 #include "zypp/CheckSum.h"
00025
00026 using std::endl;
00027
00029 namespace zypp
00030 {
00031
00032 namespace sat
00033 {
00034
00035 using detail::noSolvableId;
00036
00038
00039
00040
00042
00055 class LookupAttr::Impl
00056 {
00057 public:
00058 Impl()
00059 : _parent( SolvAttr::noAttr )
00060 {}
00061 Impl( SolvAttr attr_r, Location loc_r )
00062 : _attr( attr_r ), _parent( attr_r.parent() ), _solv( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId )
00063 {}
00064 Impl( SolvAttr attr_r, Repository repo_r, Location loc_r )
00065 : _attr( attr_r ), _parent( attr_r.parent() ), _repo( repo_r ), _solv( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId )
00066 {}
00067 Impl( SolvAttr attr_r, Solvable solv_r )
00068 : _attr( attr_r ), _parent( attr_r.parent() ), _solv( solv_r )
00069 {}
00070
00071 public:
00072 SolvAttr attr() const
00073 { return _attr; }
00074
00075 void setAttr( SolvAttr attr_r )
00076 {
00077 _attr = attr_r;
00078 SolvAttr p( _attr.parent() );
00079 if ( p != SolvAttr::noAttr )
00080 _parent = p;
00081 }
00082
00083 const AttrMatcher & attrMatcher() const
00084 { return _attrMatcher; }
00085
00086 void setAttrMatcher( const AttrMatcher & matcher_r )
00087 {
00088 matcher_r.compile();
00089 _attrMatcher = matcher_r;
00090 }
00091
00092 public:
00093 bool pool() const
00094 { return ! (_repo || _solv); }
00095
00096 void setPool( Location loc_r )
00097 {
00098 _repo = Repository::noRepository;
00099 _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId );
00100 }
00101
00102 Repository repo() const
00103 { return _repo; }
00104
00105 void setRepo( Repository repo_r, Location loc_r )
00106 {
00107 _repo = repo_r;
00108 _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId );
00109 }
00110
00111 Solvable solvable() const
00112 { return _solv; }
00113
00114 void setSolvable( Solvable solv_r )
00115 {
00116 _repo = Repository::noRepository;
00117 _solv = solv_r;
00118 }
00119
00120 SolvAttr parent() const
00121 { return _parent; }
00122
00123 void setParent( SolvAttr attr_r )
00124 { _parent = attr_r; }
00125
00126 public:
00127 LookupAttr::iterator begin() const
00128 {
00129 if ( _attr == SolvAttr::noAttr || sat::Pool::instance().reposEmpty() )
00130 return end();
00131
00132 detail::RepoIdType whichRepo = detail::noRepoId;
00133 if ( _solv )
00134 whichRepo = _solv.repository().id();
00135 else if ( _repo )
00136 whichRepo = _repo.id();
00137
00138 detail::DIWrap dip( whichRepo, _solv.id(), _attr.id(), _attrMatcher.searchstring(), _attrMatcher.flags().get() );
00139 if ( _parent != SolvAttr::noAttr )
00140 ::dataiterator_prepend_keyname( dip.get(), _parent.id() );
00141
00142 return iterator( dip );
00143 }
00144
00145 LookupAttr::iterator end() const
00146 { return iterator(); }
00147
00148 private:
00149 SolvAttr _attr;
00150 SolvAttr _parent;
00151 Repository _repo;
00152 Solvable _solv;
00153 AttrMatcher _attrMatcher;
00154
00155 private:
00156 friend Impl * rwcowClone<Impl>( const Impl * rhs );
00158 Impl * clone() const
00159 { return new Impl( *this ); }
00160 };
00161
00163
00164
00165
00167
00168 LookupAttr::LookupAttr()
00169 : _pimpl( new Impl )
00170 {}
00171
00172 LookupAttr::LookupAttr( SolvAttr attr_r, Location loc_r )
00173 : _pimpl( new Impl( attr_r, loc_r ) )
00174 {}
00175 LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Location loc_r )
00176 : _pimpl( new Impl( attr_r, loc_r ) )
00177 { _pimpl->setParent( parent_r ); }
00178
00179 LookupAttr::LookupAttr( SolvAttr attr_r, Repository repo_r, Location loc_r )
00180 : _pimpl( new Impl( attr_r, repo_r, loc_r ) )
00181 {}
00182 LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Repository repo_r, Location loc_r )
00183 : _pimpl( new Impl( attr_r, repo_r, loc_r ) )
00184 { _pimpl->setParent( parent_r ); }
00185
00186 LookupAttr::LookupAttr( SolvAttr attr_r, Solvable solv_r )
00187 : _pimpl( new Impl( attr_r, solv_r ) )
00188 {}
00189 LookupAttr::LookupAttr( SolvAttr attr_r, SolvAttr parent_r, Solvable solv_r )
00190 : _pimpl( new Impl( attr_r, solv_r ) )
00191 { _pimpl->setParent( parent_r ); }
00192
00193
00195
00196 SolvAttr LookupAttr::attr() const
00197 { return _pimpl->attr(); }
00198
00199 void LookupAttr::setAttr( SolvAttr attr_r )
00200 { _pimpl->setAttr( attr_r ); }
00201
00202 const AttrMatcher & LookupAttr::attrMatcher() const
00203 { return _pimpl->attrMatcher(); }
00204
00205 void LookupAttr::setAttrMatcher( const AttrMatcher & matcher_r )
00206 { _pimpl->setAttrMatcher( matcher_r ); }
00207
00209
00210 bool LookupAttr::pool() const
00211 { return _pimpl->pool(); }
00212
00213 void LookupAttr::setPool( Location loc_r )
00214 { _pimpl->setPool( loc_r ); }
00215
00216 Repository LookupAttr::repo() const
00217 { return _pimpl->repo(); }
00218
00219 void LookupAttr::setRepo( Repository repo_r, Location loc_r )
00220 { _pimpl->setRepo( repo_r, loc_r ); }
00221
00222 Solvable LookupAttr::solvable() const
00223 { return _pimpl->solvable(); }
00224
00225 void LookupAttr::setSolvable( Solvable solv_r )
00226 { _pimpl->setSolvable( solv_r ); }
00227
00228 SolvAttr LookupAttr::parent() const
00229 { return _pimpl->parent(); }
00230
00231 void LookupAttr::setParent( SolvAttr attr_r )
00232 { _pimpl->setParent( attr_r ); }
00233
00235
00236 LookupAttr::iterator LookupAttr::begin() const
00237 { return _pimpl->begin(); }
00238
00239 LookupAttr::iterator LookupAttr::end() const
00240 { return _pimpl->end(); }
00241
00242 bool LookupAttr::empty() const
00243 { return begin() == end(); }
00244
00245 LookupAttr::size_type LookupAttr::size() const
00246 {
00247 size_type c = 0;
00248 for_( it, begin(), end() )
00249 ++c;
00250 return c;
00251 }
00252
00254
00255 std::ostream & operator<<( std::ostream & str, const LookupAttr & obj )
00256 {
00257 if ( obj.attr() == SolvAttr::noAttr )
00258 return str << "search nothing";
00259
00260 if ( obj.attr() )
00261 str << "seach " << obj.attr() << " in ";
00262 else
00263 str << "seach ALL in ";
00264
00265 if ( obj.solvable() )
00266 return str << obj.solvable();
00267 if ( obj.repo() )
00268 return str << obj.repo();
00269 return str << "pool";
00270 }
00271
00272 std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj )
00273 {
00274 return dumpRange( str << obj, obj.begin(), obj.end() );
00275 }
00276
00278
00279
00280
00282
00283 LookupRepoAttr::LookupRepoAttr( SolvAttr attr_r, Repository repo_r )
00284 : LookupAttr( attr_r, repo_r, REPO_ATTR )
00285 {}
00286
00287 void LookupRepoAttr::setRepo( Repository repo_r )
00288 { LookupAttr::setRepo( repo_r, REPO_ATTR ); }
00289
00291
00292
00293
00295
00296 namespace detail
00297 {
00298 DIWrap::DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
00299 const std::string & mstring_r, int flags_r )
00300 : _dip( new ::Dataiterator )
00301 , _mstring( mstring_r )
00302 {
00303 ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r,
00304 _mstring.empty() ? 0 : _mstring.c_str(), flags_r );
00305 }
00306
00307 DIWrap::DIWrap( RepoIdType repoId_r, SolvableIdType solvId_r, IdType attrId_r,
00308 const char * mstring_r, int flags_r )
00309 : _dip( new ::Dataiterator )
00310 , _mstring( mstring_r ? mstring_r : "" )
00311 {
00312 ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r,
00313 _mstring.empty() ? 0 : _mstring.c_str(), flags_r );
00314 }
00315
00316 DIWrap::DIWrap( const DIWrap & rhs )
00317 : _dip( 0 )
00318 , _mstring( rhs._mstring )
00319 {
00320 if ( rhs._dip )
00321 {
00322 _dip = new ::Dataiterator;
00323 ::dataiterator_init_clone( _dip, rhs._dip );
00324 }
00325 }
00326
00327 DIWrap::~DIWrap()
00328 {
00329 if ( _dip )
00330 {
00331 ::dataiterator_free( _dip );
00332 delete _dip;
00333 }
00334 }
00335
00336 std::ostream & operator<<( std::ostream & str, const DIWrap & obj )
00337 { return str << obj.get(); }
00338 }
00339
00341
00342
00343
00345
00347
00349
00350 Repository LookupAttr::iterator::inRepo() const
00351 { return _dip ? Repository( _dip->repo ) : Repository::noRepository; }
00352
00353 Solvable LookupAttr::iterator::inSolvable() const
00354 { return _dip ? Solvable( _dip->solvid ) : Solvable::noSolvable; }
00355
00356 SolvAttr LookupAttr::iterator::inSolvAttr() const
00357 { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; }
00358
00359 void LookupAttr::iterator::nextSkipSolvAttr()
00360 { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); }
00361
00362 void LookupAttr::iterator::nextSkipSolvable()
00363 { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); }
00364
00365 void LookupAttr::iterator::nextSkipRepo()
00366 { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); }
00367
00368 void LookupAttr::iterator::stayInThisSolvable()
00369 { if ( _dip ) { _dip.get()->repoid = -1; _dip.get()->flags |= SEARCH_THISSOLVID; } }
00370
00371 void LookupAttr::iterator::stayInThisRepo()
00372 { if ( _dip ) { _dip.get()->repoid = -1; } }
00373
00375
00377
00378 detail::IdType LookupAttr::iterator::solvAttrType() const
00379 { return _dip ? _dip->key->type : detail::noId; }
00380
00381 bool LookupAttr::iterator::solvAttrNumeric() const
00382 {
00383 switch ( solvAttrType() )
00384 {
00385 case REPOKEY_TYPE_U32:
00386 case REPOKEY_TYPE_NUM:
00387 case REPOKEY_TYPE_CONSTANT:
00388 return true;
00389 break;
00390 }
00391 return false;
00392 }
00393
00394 bool LookupAttr::iterator::solvAttrString() const
00395 {
00396 switch ( solvAttrType() )
00397 {
00398 case REPOKEY_TYPE_ID:
00399 case REPOKEY_TYPE_IDARRAY:
00400 case REPOKEY_TYPE_CONSTANTID:
00401 case REPOKEY_TYPE_STR:
00402 case REPOKEY_TYPE_DIRSTRARRAY:
00403 return true;
00404 break;
00405 }
00406 return false;
00407 }
00408
00409 bool LookupAttr::iterator::solvAttrIdString() const
00410 {
00411 switch ( solvAttrType() )
00412 {
00413 case REPOKEY_TYPE_ID:
00414 case REPOKEY_TYPE_IDARRAY:
00415 case REPOKEY_TYPE_CONSTANTID:
00416 return true;
00417 break;
00418 }
00419 return false;
00420 }
00421
00422 bool LookupAttr::iterator::solvAttrCheckSum() const
00423 {
00424 switch ( solvAttrType() )
00425 {
00426 case REPOKEY_TYPE_MD5:
00427 case REPOKEY_TYPE_SHA1:
00428 case REPOKEY_TYPE_SHA256:
00429 return true;
00430 break;
00431 }
00432 return false;
00433 }
00434
00436 namespace
00437 {
00438 enum SubType { ST_NONE,
00439 ST_FLEX,
00440 ST_SUB };
00441 SubType subType( const detail::DIWrap & dip )
00442 {
00443 if ( ! dip )
00444 return ST_NONE;
00445 if ( dip.get()->key->type == REPOKEY_TYPE_FLEXARRAY )
00446 return ST_FLEX;
00447 return dip.get()->kv.parent ? ST_SUB : ST_NONE;
00448 }
00449 }
00451
00452 bool LookupAttr::iterator::solvAttrSubEntry() const
00453 { return subType( _dip ) != ST_NONE; }
00454
00456
00458
00459 bool LookupAttr::iterator::subEmpty() const
00460 { return( subBegin() == subEnd() ); }
00461
00462 LookupAttr::size_type LookupAttr::iterator::subSize() const
00463 {
00464 size_type c = 0;
00465 for_( it, subBegin(), subEnd() )
00466 ++c;
00467 return c;
00468 }
00469
00470 LookupAttr::iterator LookupAttr::iterator::subBegin() const
00471 {
00472 SubType subtype( subType( _dip ) );
00473 if ( subtype == ST_NONE )
00474 return subEnd();
00475
00476 detail::DIWrap dip( 0, 0, 0 );
00477 ::dataiterator_clonepos( dip.get(), _dip.get() );
00478 switch ( subtype )
00479 {
00480 case ST_NONE:
00481 break;
00482 case ST_FLEX:
00483 ::dataiterator_seek( dip.get(), DI_SEEK_CHILD|DI_SEEK_STAY );
00484 break;
00485 case ST_SUB:
00486 ::dataiterator_seek( dip.get(), DI_SEEK_REWIND|DI_SEEK_STAY );
00487 break;
00488 }
00489 return iterator( dip );
00490 }
00491
00492 LookupAttr::iterator LookupAttr::iterator::subEnd() const
00493 {
00494 return iterator();
00495 }
00496
00497 LookupAttr::iterator LookupAttr::iterator::subFind( SolvAttr attr_r ) const
00498 {
00499 iterator it = subBegin();
00500 if ( attr_r != sat::SolvAttr::allAttr )
00501 {
00502 while ( it != subEnd() && it.inSolvAttr() != attr_r )
00503 ++it;
00504 }
00505 return it;
00506 }
00507
00508 LookupAttr::iterator LookupAttr::iterator::subFind( const C_Str & attrname_r ) const
00509 {
00510 if ( attrname_r.empty() )
00511 return subBegin();
00512
00513 SubType subtype( subType( _dip ) );
00514 if ( subtype == ST_NONE )
00515 return subBegin();
00516
00517 std::string subattr( inSolvAttr().asString() );
00518 if ( subtype == ST_FLEX )
00519 {
00520
00521 subattr += ":";
00522 subattr += attrname_r;
00523 }
00524 else
00525 {
00526
00527 std::string::size_type pos( subattr.rfind( ':' ) );
00528 if ( pos != std::string::npos )
00529 {
00530 subattr.erase( pos+1 );
00531 subattr += attrname_r;
00532 }
00533 else
00534 subattr = attrname_r;
00535 }
00536 return subFind( SolvAttr( subattr ) );
00537 }
00538
00540
00542
00543 int LookupAttr::iterator::asInt() const
00544 {
00545 if ( _dip )
00546 {
00547 switch ( solvAttrType() )
00548 {
00549 case REPOKEY_TYPE_U32:
00550 case REPOKEY_TYPE_NUM:
00551 case REPOKEY_TYPE_CONSTANT:
00552 return _dip->kv.num;
00553 break;
00554 }
00555 }
00556 return 0;
00557 }
00558
00559 unsigned LookupAttr::iterator::asUnsigned() const
00560 { return asInt(); }
00561
00562 bool LookupAttr::iterator::asBool() const
00563 { return asInt(); }
00564
00565
00566 const char * LookupAttr::iterator::c_str() const
00567 {
00568 if ( _dip )
00569 {
00570 switch ( solvAttrType() )
00571 {
00572 case REPOKEY_TYPE_ID:
00573 case REPOKEY_TYPE_IDARRAY:
00574 case REPOKEY_TYPE_CONSTANTID:
00575 if ( _dip->data && _dip->data->localpool )
00576 return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id );
00577 else
00578 return IdString( _dip->kv.id ).c_str();
00579 break;
00580
00581 case REPOKEY_TYPE_STR:
00582 return _dip->kv.str;
00583 break;
00584
00585 case REPOKEY_TYPE_DIRSTRARRAY:
00586 return ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str );
00587 break;
00588 }
00589 }
00590 return 0;
00591 }
00592
00593 std::string LookupAttr::iterator::asString() const
00594 {
00595 if ( _dip )
00596 {
00597 switch ( solvAttrType() )
00598 {
00599 case REPOKEY_TYPE_ID:
00600 case REPOKEY_TYPE_IDARRAY:
00601 case REPOKEY_TYPE_CONSTANTID:
00602 {
00603 detail::IdType id = ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 );
00604 return ISRELDEP(id) ? Capability( id ).asString()
00605 : IdString( id ).asString();
00606 }
00607 break;
00608
00609 case REPOKEY_TYPE_STR:
00610 case REPOKEY_TYPE_DIRSTRARRAY:
00611 {
00612 const char * ret( c_str() );
00613 return ret ? ret : "";
00614 }
00615 break;
00616
00617 case REPOKEY_TYPE_U32:
00618 case REPOKEY_TYPE_NUM:
00619 case REPOKEY_TYPE_CONSTANT:
00620 return str::numstring( asInt() );
00621 break;
00622
00623 case REPOKEY_TYPE_MD5:
00624 case REPOKEY_TYPE_SHA1:
00625 case REPOKEY_TYPE_SHA256:
00626 {
00627 return asCheckSum().asString();
00628 }
00629 break;
00630
00631 case REPOKEY_TYPE_FLEXARRAY:
00632 {
00633 std::ostringstream str;
00634 str << "{" << endl;
00635 for_( it, subBegin(), subEnd() )
00636 {
00637 str << " " << it.inSolvAttr() << " = " << it.asString() << endl;
00638 }
00639 str << "}";
00640 return str.str();
00641 }
00642 break;
00643 }
00644 }
00645 return std::string();
00646 }
00647
00648 IdString LookupAttr::iterator::idStr() const
00649 {
00650 if ( _dip )
00651 {
00652 switch ( solvAttrType() )
00653 {
00654 case REPOKEY_TYPE_ID:
00655 case REPOKEY_TYPE_IDARRAY:
00656 case REPOKEY_TYPE_CONSTANTID:
00657 return IdString( ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 ) );
00658 break;
00659 }
00660 }
00661 return IdString();
00662 }
00663
00664 CheckSum LookupAttr::iterator::asCheckSum() const
00665 {
00666 if ( _dip )
00667 {
00668 switch ( solvAttrType() )
00669 {
00670 case REPOKEY_TYPE_MD5:
00671 return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
00672 break;
00673
00674 case REPOKEY_TYPE_SHA1:
00675 return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
00676 break;
00677
00678 case REPOKEY_TYPE_SHA256:
00679 return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
00680 break;
00681 }
00682 }
00683 return CheckSum();
00684 }
00685
00687
00689
00690 LookupAttr::iterator::iterator()
00691 : iterator_adaptor_( 0 )
00692 {}
00693
00694 LookupAttr::iterator::iterator( const iterator & rhs )
00695 : iterator_adaptor_( 0 )
00696 , _dip( rhs._dip )
00697 {
00698 base_reference() = _dip.get();
00699 }
00700
00701 LookupAttr::iterator::iterator( detail::DIWrap & dip_r )
00702 : iterator_adaptor_( 0 )
00703 {
00704 _dip.swap( dip_r );
00705 base_reference() = _dip.get();
00706 increment();
00707 }
00708
00709 LookupAttr::iterator::~iterator()
00710 {}
00711
00712 LookupAttr::iterator & LookupAttr::iterator::operator=( const iterator & rhs )
00713 {
00714 if ( &rhs != this )
00715 {
00716 _dip = rhs._dip;
00717 base_reference() = _dip.get();
00718 }
00719 return *this;
00720 }
00721
00723
00724 bool LookupAttr::iterator::dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const
00725 {
00726
00727
00728 return( lhs.solvid == rhs.solvid && lhs.key->name == rhs.key->name );
00729 }
00730
00731 detail::IdType LookupAttr::iterator::dereference() const
00732 {
00733 return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 )
00734 : detail::noId;
00735 }
00736
00737 void LookupAttr::iterator::increment()
00738 {
00739 if ( _dip && ! ::dataiterator_step( _dip.get() ) )
00740 {
00741 _dip.reset();
00742 base_reference() = 0;
00743 }
00744 }
00745
00746 std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
00747 {
00748 const ::_Dataiterator * dip = obj.get();
00749 if ( ! dip )
00750 return str << "EndOfQuery";
00751
00752 if ( obj.inSolvable() )
00753 str << obj.inSolvable();
00754 else if ( obj.inRepo() )
00755 str << obj.inRepo();
00756
00757 str << '<' << obj.inSolvAttr() << (obj.solvAttrSubEntry() ? ">(*" : ">(")
00758 << IdString(obj.solvAttrType()) << ") = " << obj.asString();
00759 return str;
00760 }
00761
00762 template<> CheckSum LookupAttr::iterator::asType<CheckSum>() const
00763 { return asCheckSum(); }
00764
00766 }
00769 }
00771
00772 std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj )
00773 {
00774 str << "::_Dataiterator(";
00775 if ( ! obj )
00776 {
00777 str << "NULL";
00778 }
00779 else
00780 {
00781 str << "|" << zypp::Repository(obj->repo);
00782 str << "|" << zypp::sat::Solvable(obj->solvid);
00783 str << "|" << zypp::IdString(obj->key->name);
00784 str << "|" << zypp::IdString(obj->key->type);
00785 str << "|" << obj->repodataid;
00786 str << "|" << obj->repoid;
00787 }
00788 return str << ")";
00789 }
00790