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_U32:
387 case REPOKEY_TYPE_NUM:
388 case REPOKEY_TYPE_CONSTANT:
395 bool LookupAttr::iterator::solvAttrString() const
397 switch ( solvAttrType() )
399 case REPOKEY_TYPE_ID:
400 case REPOKEY_TYPE_IDARRAY:
401 case REPOKEY_TYPE_CONSTANTID:
402 case REPOKEY_TYPE_STR:
403 case REPOKEY_TYPE_DIRSTRARRAY:
410 bool LookupAttr::iterator::solvAttrIdString() const
412 switch ( solvAttrType() )
414 case REPOKEY_TYPE_ID:
415 case REPOKEY_TYPE_IDARRAY:
416 case REPOKEY_TYPE_CONSTANTID:
423 bool LookupAttr::iterator::solvAttrCheckSum() const
425 switch ( solvAttrType() )
427 case REPOKEY_TYPE_MD5:
428 case REPOKEY_TYPE_SHA1:
429 case REPOKEY_TYPE_SHA256:
436 ///////////////////////////////////////////////////////////////////
439 enum SubType { ST_NONE, // no sub-structure
440 ST_FLEX, // flexarray
441 ST_SUB }; // inside sub-structure
442 SubType subType( const detail::DIWrap & dip )
446 if ( dip.get()->key->type == REPOKEY_TYPE_FLEXARRAY )
448 return dip.get()->kv.parent ? ST_SUB : ST_NONE;
451 ///////////////////////////////////////////////////////////////////
453 bool LookupAttr::iterator::solvAttrSubEntry() const
454 { return subType( _dip ) != ST_NONE; }
456 ///////////////////////////////////////////////////////////////////
457 // Iterate sub-structures.
458 ///////////////////////////////////////////////////////////////////
460 bool LookupAttr::iterator::subEmpty() const
461 { return( subBegin() == subEnd() ); }
463 LookupAttr::size_type LookupAttr::iterator::subSize() const
466 for_( it, subBegin(), subEnd() )
471 LookupAttr::iterator LookupAttr::iterator::subBegin() const
473 SubType subtype( subType( _dip ) );
474 if ( subtype == ST_NONE )
476 // setup the new sub iterator with the remembered position
477 detail::DIWrap dip( 0, 0, 0 );
478 ::dataiterator_clonepos( dip.get(), _dip.get() );
481 case ST_NONE: // not reached
484 ::dataiterator_seek( dip.get(), DI_SEEK_CHILD|DI_SEEK_STAY );
487 ::dataiterator_seek( dip.get(), DI_SEEK_REWIND|DI_SEEK_STAY );
490 return iterator( dip ); // iterator takes over ownership!
493 LookupAttr::iterator LookupAttr::iterator::subEnd() const
498 LookupAttr::iterator LookupAttr::iterator::subFind( SolvAttr attr_r ) const
500 iterator it = subBegin();
501 if ( attr_r != sat::SolvAttr::allAttr )
503 while ( it != subEnd() && it.inSolvAttr() != attr_r )
509 LookupAttr::iterator LookupAttr::iterator::subFind( const C_Str & attrname_r ) const
511 if ( attrname_r.empty() )
514 SubType subtype( subType( _dip ) );
515 if ( subtype == ST_NONE )
518 std::string subattr( inSolvAttr().asString() );
519 if ( subtype == ST_FLEX )
521 // append ":attrname"
523 subattr += attrname_r;
527 // replace "oldname" after ':' with "attrname"
528 std::string::size_type pos( subattr.rfind( ':' ) );
529 if ( pos != std::string::npos )
531 subattr.erase( pos+1 );
532 subattr += attrname_r;
535 subattr = attrname_r; // no ':' so replace all.
537 return subFind( SolvAttr( subattr ) );
540 ///////////////////////////////////////////////////////////////////
541 // attr value retrieval
542 ///////////////////////////////////////////////////////////////////
544 int LookupAttr::iterator::asInt() const
548 switch ( solvAttrType() )
550 case REPOKEY_TYPE_U32:
551 case REPOKEY_TYPE_NUM:
552 case REPOKEY_TYPE_CONSTANT:
560 unsigned LookupAttr::iterator::asUnsigned() const
563 unsigned long long LookupAttr::iterator::asUnsignedLL() const
567 switch ( solvAttrType() )
569 case REPOKEY_TYPE_U32:
570 case REPOKEY_TYPE_NUM:
571 case REPOKEY_TYPE_CONSTANT:
572 return SOLV_KV_NUM64(&_dip->kv);
579 bool LookupAttr::iterator::asBool() const
583 const char * LookupAttr::iterator::c_str() const
587 switch ( solvAttrType() )
589 case REPOKEY_TYPE_ID:
590 case REPOKEY_TYPE_IDARRAY:
591 case REPOKEY_TYPE_CONSTANTID:
592 if ( _dip->data && _dip->data->localpool )
593 return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id ); // in local pool
595 return IdString( _dip->kv.id ).c_str(); // in global pool
598 case REPOKEY_TYPE_STR:
602 case REPOKEY_TYPE_DIRSTRARRAY:
603 // may or may not be stringified depending on SEARCH_FILES flag
604 return( _dip->flags & SEARCH_FILES
606 : ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str ) );
613 std::string LookupAttr::iterator::asString() const
617 switch ( solvAttrType() )
619 case REPOKEY_TYPE_ID:
620 case REPOKEY_TYPE_IDARRAY:
621 case REPOKEY_TYPE_CONSTANTID:
623 detail::IdType id = ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 );
624 return ISRELDEP(id) ? Capability( id ).asString()
625 : IdString( id ).asString();
629 case REPOKEY_TYPE_STR:
630 case REPOKEY_TYPE_DIRSTRARRAY:
632 const char * ret( c_str() );
633 return ret ? ret : "";
637 case REPOKEY_TYPE_U32:
638 case REPOKEY_TYPE_NUM:
639 case REPOKEY_TYPE_CONSTANT:
640 return str::numstring( asInt() );
643 case REPOKEY_TYPE_MD5:
644 case REPOKEY_TYPE_SHA1:
645 case REPOKEY_TYPE_SHA256:
647 return asCheckSum().asString();
651 case REPOKEY_TYPE_FLEXARRAY:
653 std::ostringstream str;
655 for_( it, subBegin(), subEnd() )
657 str << " " << it.inSolvAttr() << " = " << it.asString() << endl;
665 return std::string();
668 IdString LookupAttr::iterator::idStr() const
672 switch ( solvAttrType() )
674 case REPOKEY_TYPE_ID:
675 case REPOKEY_TYPE_IDARRAY:
676 case REPOKEY_TYPE_CONSTANTID:
677 return IdString( ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 ) );
684 CheckSum LookupAttr::iterator::asCheckSum() const
688 switch ( solvAttrType() )
690 case REPOKEY_TYPE_MD5:
691 return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
694 case REPOKEY_TYPE_SHA1:
695 return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
698 case REPOKEY_TYPE_SHA224:
699 return CheckSum::sha224( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
702 case REPOKEY_TYPE_SHA256:
703 return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
706 case REPOKEY_TYPE_SHA384:
707 return CheckSum::sha384( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
710 case REPOKEY_TYPE_SHA512:
711 return CheckSum::sha512( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
718 ///////////////////////////////////////////////////////////////////
719 // internal stuff below
720 ///////////////////////////////////////////////////////////////////
722 LookupAttr::iterator::iterator()
723 : iterator_adaptor_( 0 )
726 LookupAttr::iterator::iterator( const iterator & rhs )
727 : iterator_adaptor_( 0 )
730 base_reference() = _dip.get();
733 LookupAttr::iterator::iterator( detail::DIWrap & dip_r )
734 : iterator_adaptor_( 0 )
736 _dip.swap( dip_r ); // take ownership!
737 base_reference() = _dip.get();
741 LookupAttr::iterator::~iterator()
744 LookupAttr::iterator & LookupAttr::iterator::operator=( const iterator & rhs )
749 base_reference() = _dip.get();
754 ///////////////////////////////////////////////////////////////////
756 bool LookupAttr::iterator::dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const
758 // Iterator equal is same position in same container.
759 // Here: same attribute in same solvable.
760 return( lhs.solvid == rhs.solvid && lhs.key->name == rhs.key->name );
763 detail::IdType LookupAttr::iterator::dereference() const
765 return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 )
769 void LookupAttr::iterator::increment()
773 if ( ! ::dataiterator_step( _dip.get() ) )
776 base_reference() = 0;
780 ::dataiterator_strdup( _dip.get() );
785 std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
787 const ::_Dataiterator * dip = obj.get();
789 return str << "EndOfQuery";
791 if ( obj.inSolvable() )
792 str << obj.inSolvable();
793 else if ( obj.inRepo() )
796 str << '<' << obj.inSolvAttr() << (obj.solvAttrSubEntry() ? ">(*" : ">(")
797 << IdString(obj.solvAttrType()) << ") = " << obj.asString();
801 template<> CheckSum LookupAttr::iterator::asType<CheckSum>() const
802 { return asCheckSum(); }
804 /////////////////////////////////////////////////////////////////
806 ///////////////////////////////////////////////////////////////////
807 /////////////////////////////////////////////////////////////////
809 ///////////////////////////////////////////////////////////////////
811 std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj )
813 str << "::_Dataiterator(";
820 str << "|" << zypp::Repository(obj->repo);
821 str << "|" << zypp::sat::Solvable(obj->solvid);
822 str << "|" << zypp::IdString(obj->key->name);
823 str << "|" << zypp::IdString(obj->key->type);
824 str << "|" << obj->repodataid;
825 str << "|" << obj->repoid;
830 ///////////////////////////////////////////////////////////////////