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/sat/AttrMatcher.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 AttrMatcher & attrMatcher() const
84 { return _attrMatcher; }
86 void setAttrMatcher( const AttrMatcher & matcher_r )
89 _attrMatcher = 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(), _attrMatcher.searchstring(), _attrMatcher.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 AttrMatcher _attrMatcher;
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 AttrMatcher & LookupAttr::attrMatcher() const
203 { return _pimpl->attrMatcher(); }
205 void LookupAttr::setAttrMatcher( const AttrMatcher & matcher_r )
206 { _pimpl->setAttrMatcher( 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;
324 if ( _dip->nparents )
326 for ( int i = 1; i < _dip->nparents; ++i )
328 _dip->parents[i].kv.parent = &_dip->parents[i-1].kv;
330 _dip->kv.parent = &_dip->parents[_dip->nparents-1].kv;
332 // now we have to manually clone any allocated regex data matcher.
333 ::Datamatcher & matcher( _dip->matcher );
334 if ( matcher.match && ( matcher.flags & SEARCH_STRINGMASK ) == SEARCH_REGEX )
336 ::datamatcher_init( &matcher, _mstring.c_str(), matcher.flags );
338 else if ( matcher.match && matcher.match != _mstring.c_str() )
340 //SEC << "**" << rhs._dip << endl;
341 SEC << "r " << rhs._dip->matcher.match << endl;
342 SEC << "r " << rhs._dip->matcher.flags << endl;
343 SEC << "r " << (const void*)rhs._mstring.c_str() << "'" << rhs._mstring << "'" << endl;
345 SEC << "t " << matcher.match << endl;
346 SEC << "t " << matcher.flags << endl;
347 SEC << "t " << (const void*)_mstring.c_str() << "'" << _mstring << "'" << endl;
348 throw( "this cant be!" );
357 ::dataiterator_free( _dip );
362 std::ostream & operator<<( std::ostream & str, const DIWrap & obj )
363 { return str << obj.get(); }
366 ///////////////////////////////////////////////////////////////////
368 // CLASS NAME : LookupAttr::iterator
370 ///////////////////////////////////////////////////////////////////
372 ///////////////////////////////////////////////////////////////////
373 // position and moving
374 ///////////////////////////////////////////////////////////////////
376 Repository LookupAttr::iterator::inRepo() const
377 { return _dip ? Repository( _dip->repo ) : Repository::noRepository; }
379 Solvable LookupAttr::iterator::inSolvable() const
380 { return _dip ? Solvable( _dip->solvid ) : Solvable::noSolvable; }
382 SolvAttr LookupAttr::iterator::inSolvAttr() const
383 { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; }
385 void LookupAttr::iterator::nextSkipSolvAttr()
386 { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); }
388 void LookupAttr::iterator::nextSkipSolvable()
389 { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); }
391 void LookupAttr::iterator::nextSkipRepo()
392 { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); }
394 void LookupAttr::iterator::stayInThisSolvable()
395 { if ( _dip ) { _dip.get()->repoid = -1; _dip.get()->flags |= SEARCH_THISSOLVID; } }
397 void LookupAttr::iterator::stayInThisRepo()
398 { if ( _dip ) { _dip.get()->repoid = -1; } }
400 ///////////////////////////////////////////////////////////////////
401 // attr value type test
402 ///////////////////////////////////////////////////////////////////
404 detail::IdType LookupAttr::iterator::solvAttrType() const
405 { return _dip ? _dip->key->type : detail::noId; }
407 bool LookupAttr::iterator::solvAttrNumeric() const
409 switch ( solvAttrType() )
411 case REPOKEY_TYPE_U32:
412 case REPOKEY_TYPE_NUM:
413 case REPOKEY_TYPE_CONSTANT:
420 bool LookupAttr::iterator::solvAttrString() const
422 switch ( solvAttrType() )
424 case REPOKEY_TYPE_ID:
425 case REPOKEY_TYPE_IDARRAY:
426 case REPOKEY_TYPE_CONSTANTID:
427 case REPOKEY_TYPE_STR:
428 case REPOKEY_TYPE_DIRSTRARRAY:
435 bool LookupAttr::iterator::solvAttrIdString() const
437 switch ( solvAttrType() )
439 case REPOKEY_TYPE_ID:
440 case REPOKEY_TYPE_IDARRAY:
441 case REPOKEY_TYPE_CONSTANTID:
448 bool LookupAttr::iterator::solvAttrCheckSum() const
450 switch ( solvAttrType() )
452 case REPOKEY_TYPE_MD5:
453 case REPOKEY_TYPE_SHA1:
454 case REPOKEY_TYPE_SHA256:
461 ///////////////////////////////////////////////////////////////////
464 enum SubType { ST_NONE, // no sub-structure
465 ST_FLEX, // flexarray
466 ST_SUB }; // inside sub-structure
467 SubType subType( const detail::DIWrap & dip )
471 if ( dip.get()->key->type == REPOKEY_TYPE_FLEXARRAY )
473 return dip.get()->kv.parent ? ST_SUB : ST_NONE;
476 ///////////////////////////////////////////////////////////////////
478 bool LookupAttr::iterator::solvAttrSubEntry() const
479 { return subType( _dip ) != ST_NONE; }
481 ///////////////////////////////////////////////////////////////////
482 // Iterate sub-structures.
483 ///////////////////////////////////////////////////////////////////
485 bool LookupAttr::iterator::subEmpty() const
486 { return( subBegin() == subEnd() ); }
488 LookupAttr::size_type LookupAttr::iterator::subSize() const
491 for_( it, subBegin(), subEnd() )
496 LookupAttr::iterator LookupAttr::iterator::subBegin() const
498 switch ( subType( _dip ) )
504 ::dataiterator_setpos( _dip.get() );
507 ::dataiterator_setpos_parent( _dip.get() );
510 // setup the new sub iterator with the remembered position
511 detail::DIWrap dip( 0, SOLVID_POS, 0, 0, 0 );
512 return iterator( dip ); // iterator takes over ownership!
515 LookupAttr::iterator LookupAttr::iterator::subEnd() const
520 LookupAttr::iterator LookupAttr::iterator::subFind( SolvAttr attr_r ) const
522 iterator it = subBegin();
523 if ( attr_r != sat::SolvAttr::allAttr )
525 while ( it != subEnd() && it.inSolvAttr() != attr_r )
531 LookupAttr::iterator LookupAttr::iterator::subFind( const C_Str & attrname_r ) const
533 if ( attrname_r.empty() )
536 SubType subtype( subType( _dip ) );
537 if ( subtype == ST_NONE )
540 std::string subattr( inSolvAttr().asString() );
541 if ( subtype == ST_FLEX )
543 // append ":attrname"
545 subattr += attrname_r;
549 // replace "oldname" after ':' with "attrname"
550 std::string::size_type pos( subattr.rfind( ':' ) );
551 if ( pos != std::string::npos )
553 subattr.erase( pos+1 );
554 subattr += attrname_r;
557 subattr = attrname_r; // no ':' so replace all.
559 return subFind( SolvAttr( subattr ) );
562 ///////////////////////////////////////////////////////////////////
563 // attr value retrieval
564 ///////////////////////////////////////////////////////////////////
566 int LookupAttr::iterator::asInt() const
570 switch ( solvAttrType() )
572 case REPOKEY_TYPE_U32:
573 case REPOKEY_TYPE_NUM:
574 case REPOKEY_TYPE_CONSTANT:
582 unsigned LookupAttr::iterator::asUnsigned() const
585 bool LookupAttr::iterator::asBool() const
589 const char * LookupAttr::iterator::c_str() const
593 switch ( solvAttrType() )
595 case REPOKEY_TYPE_ID:
596 case REPOKEY_TYPE_IDARRAY:
597 case REPOKEY_TYPE_CONSTANTID:
598 if ( _dip->data && _dip->data->localpool )
599 return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id ); // in local pool
601 return IdString( _dip->kv.id ).c_str(); // in global pool
604 case REPOKEY_TYPE_STR:
608 case REPOKEY_TYPE_DIRSTRARRAY:
609 return ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str );
616 std::string LookupAttr::iterator::asString() const
620 switch ( solvAttrType() )
622 case REPOKEY_TYPE_ID:
623 case REPOKEY_TYPE_IDARRAY:
624 case REPOKEY_TYPE_CONSTANTID:
626 detail::IdType id = ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 );
627 return ISRELDEP(id) ? Capability( id ).asString()
628 : IdString( id ).asString();
632 case REPOKEY_TYPE_STR:
633 case REPOKEY_TYPE_DIRSTRARRAY:
635 const char * ret( c_str() );
636 return ret ? ret : "";
640 case REPOKEY_TYPE_U32:
641 case REPOKEY_TYPE_NUM:
642 case REPOKEY_TYPE_CONSTANT:
643 return str::numstring( asInt() );
646 case REPOKEY_TYPE_MD5:
647 case REPOKEY_TYPE_SHA1:
648 case REPOKEY_TYPE_SHA256:
650 return asCheckSum().asString();
654 case REPOKEY_TYPE_FLEXARRAY:
656 std::ostringstream str;
658 for_( it, subBegin(), subEnd() )
660 str << " " << it.inSolvAttr() << " = " << it.asString() << endl;
668 return std::string();
671 IdString LookupAttr::iterator::idStr() const
675 switch ( solvAttrType() )
677 case REPOKEY_TYPE_ID:
678 case REPOKEY_TYPE_IDARRAY:
679 case REPOKEY_TYPE_CONSTANTID:
680 return IdString( ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 ) );
687 CheckSum LookupAttr::iterator::asCheckSum() const
691 switch ( solvAttrType() )
693 case REPOKEY_TYPE_MD5:
694 return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
697 case REPOKEY_TYPE_SHA1:
698 return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
701 case REPOKEY_TYPE_SHA256:
702 return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
709 ///////////////////////////////////////////////////////////////////
710 // internal stuff below
711 ///////////////////////////////////////////////////////////////////
713 LookupAttr::iterator::iterator()
714 : iterator_adaptor_( 0 )
717 LookupAttr::iterator::iterator( const iterator & rhs )
718 : iterator_adaptor_( 0 )
721 base_reference() = _dip.get();
724 LookupAttr::iterator::iterator( detail::DIWrap & dip_r )
725 : iterator_adaptor_( 0 )
727 _dip.swap( dip_r ); // take ownership!
728 base_reference() = _dip.get();
732 LookupAttr::iterator::~iterator()
735 LookupAttr::iterator & LookupAttr::iterator::operator=( const iterator & rhs )
740 base_reference() = _dip.get();
745 ///////////////////////////////////////////////////////////////////
747 bool LookupAttr::iterator::dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const
749 // Iterator equal is same position in same container.
750 // Here: same attribute in same solvable.
751 return( lhs.solvid == rhs.solvid && lhs.key->name == rhs.key->name );
754 detail::IdType LookupAttr::iterator::dereference() const
756 return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 )
760 void LookupAttr::iterator::increment()
762 if ( _dip && ! ::dataiterator_step( _dip.get() ) )
765 base_reference() = 0;
769 std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
771 const ::_Dataiterator * dip = obj.get();
773 return str << "EndOfQuery";
775 if ( obj.inSolvable() )
776 str << obj.inSolvable();
777 else if ( obj.inRepo() )
780 str << '<' << obj.inSolvAttr() << (obj.solvAttrSubEntry() ? ">(*" : ">(")
781 << IdString(obj.solvAttrType()) << ") = " << obj.asString();
785 template<> CheckSum LookupAttr::iterator::asType<CheckSum>() const
786 { return asCheckSum(); }
788 /////////////////////////////////////////////////////////////////
790 ///////////////////////////////////////////////////////////////////
791 /////////////////////////////////////////////////////////////////
793 ///////////////////////////////////////////////////////////////////
795 std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj )
797 str << "::_Dataiterator(";
804 str << "|" << zypp::Repository(obj->repo);
805 str << "|" << zypp::sat::Solvable(obj->solvid);
806 str << "|" << zypp::IdString(obj->key->name);
807 str << "|" << zypp::IdString(obj->key->type);
808 str << "|" << obj->repodataid;
809 str << "|" << obj->repoid;
814 ///////////////////////////////////////////////////////////////////