libzypp  11.13.5
LookupAttr.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
12 #include <iostream>
13 #include <sstream>
14 
15 #include "zypp/base/LogTools.h"
16 #include "zypp/base/String.h"
17 
19 
20 #include "zypp/sat/Pool.h"
21 #include "zypp/sat/LookupAttr.h"
22 #include "zypp/base/StrMatcher.h"
23 
24 #include "zypp/CheckSum.h"
25 
26 using std::endl;
27 
29 namespace zypp
30 {
31 
32  namespace sat
33  {
34 
36 
38  //
39  // CLASS NAME : LookupAttr::Impl
40  //
42 
56  {
57  public:
58  Impl()
59  : _parent( SolvAttr::noAttr )
60  {}
61  Impl( SolvAttr attr_r, Location loc_r )
62  : _attr( attr_r ), _parent( attr_r.parent() ), _solv( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId )
63  {}
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 )
66  {}
67  Impl( SolvAttr attr_r, Solvable solv_r )
68  : _attr( attr_r ), _parent( attr_r.parent() ), _solv( solv_r )
69  {}
70 
71  public:
72  SolvAttr attr() const
73  { return _attr; }
74 
75  void setAttr( SolvAttr attr_r )
76  {
77  _attr = attr_r;
78  SolvAttr p( _attr.parent() );
79  if ( p != SolvAttr::noAttr )
80  _parent = p;
81  }
82 
83  const StrMatcher & strMatcher() const
84  { return _strMatcher; }
85 
86  void setStrMatcher( const StrMatcher & matcher_r )
87  {
88  matcher_r.compile();
89  _strMatcher = matcher_r;
90  }
91 
92  public:
93  bool pool() const
94  { return ! (_repo || _solv); }
95 
96  void setPool( Location loc_r )
97  {
99  _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId );
100  }
101 
102  Repository repo() const
103  { return _repo; }
104 
105  void setRepo( Repository repo_r, Location loc_r )
106  {
107  _repo = repo_r;
108  _solv = Solvable( loc_r == REPO_ATTR ? SOLVID_META : noSolvableId );
109  }
110 
112  { return _solv; }
113 
114  void setSolvable( Solvable solv_r )
115  {
117  _solv = solv_r;
118  }
119 
120  SolvAttr parent() const
121  { return _parent; }
122 
123  void setParent( SolvAttr attr_r )
124  { _parent = attr_r; }
125 
126  public:
128  {
129  if ( _attr == SolvAttr::noAttr || sat::Pool::instance().reposEmpty() )
130  return end();
131 
132  detail::RepoIdType whichRepo = detail::noRepoId; // all repos
133  if ( _solv )
134  whichRepo = _solv.repository().id();
135  else if ( _repo )
136  whichRepo = _repo.id();
137 
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() );
141 
142  return iterator( dip ); // iterator takes over ownership!
143  }
144 
146  { return iterator(); }
147 
148  private:
154 
155  private:
156  friend Impl * rwcowClone<Impl>( const Impl * rhs );
158  Impl * clone() const
159  { return new Impl( *this ); }
160  };
161 
163  //
164  // CLASS NAME : LookupAttr
165  //
167 
169  : _pimpl( new Impl )
170  {}
171 
173  : _pimpl( new Impl( attr_r, loc_r ) )
174  {}
176  : _pimpl( new Impl( attr_r, loc_r ) )
177  { _pimpl->setParent( parent_r ); }
178 
180  : _pimpl( new Impl( attr_r, repo_r, loc_r ) )
181  {}
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 ); }
185 
187  : _pimpl( new Impl( attr_r, solv_r ) )
188  {}
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 ); }
192 
193 
195 
197  { return _pimpl->attr(); }
198 
200  { _pimpl->setAttr( attr_r ); }
201 
203  { return _pimpl->strMatcher(); }
204 
205  void LookupAttr::setStrMatcher( const StrMatcher & matcher_r )
206  { _pimpl->setStrMatcher( matcher_r ); }
207 
209 
210  bool LookupAttr::pool() const
211  { return _pimpl->pool(); }
212 
214  { _pimpl->setPool( loc_r ); }
215 
217  { return _pimpl->repo(); }
218 
220  { _pimpl->setRepo( repo_r, loc_r ); }
221 
223  { return _pimpl->solvable(); }
224 
226  { _pimpl->setSolvable( solv_r ); }
227 
229  { return _pimpl->parent(); }
230 
232  { _pimpl->setParent( attr_r ); }
233 
235 
237  { return _pimpl->begin(); }
238 
240  { return _pimpl->end(); }
241 
242  bool LookupAttr::empty() const
243  { return begin() == end(); }
244 
246  {
247  size_type c = 0;
248  for_( it, begin(), end() )
249  ++c;
250  return c;
251  }
252 
254 
255  std::ostream & operator<<( std::ostream & str, const LookupAttr & obj )
256  {
257  if ( obj.attr() == SolvAttr::noAttr )
258  return str << "search nothing";
259 
260  if ( obj.attr() )
261  str << "seach " << obj.attr() << " in ";
262  else
263  str << "seach ALL in ";
264 
265  if ( obj.solvable() )
266  return str << obj.solvable();
267  if ( obj.repo() )
268  return str << obj.repo();
269  return str << "pool";
270  }
271 
272  std::ostream & dumpOn( std::ostream & str, const LookupAttr & obj )
273  {
274  return dumpRange( str << obj, obj.begin(), obj.end() );
275  }
276 
278  //
279  // CLASS NAME : LookupRepoAttr
280  //
282 
284  : LookupAttr( attr_r, repo_r, REPO_ATTR )
285  {}
286 
288  { LookupAttr::setRepo( repo_r, REPO_ATTR ); }
289 
291  //
292  // CLASS NAME : detail::DIWrap
293  //
295 
296  namespace detail
297  {
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 )
302  {
303  ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r,
304  _mstring.empty() ? 0 : _mstring.c_str(), flags_r );
305  }
306 
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 : "" )
311  {
312  ::dataiterator_init( _dip, sat::Pool::instance().get(), repoId_r, solvId_r, attrId_r,
313  _mstring.empty() ? 0 : _mstring.c_str(), flags_r );
314  }
315 
316  DIWrap::DIWrap( const DIWrap & rhs )
317  : _dip( 0 )
318  , _mstring( rhs._mstring )
319  {
320  if ( rhs._dip )
321  {
322  _dip = new ::Dataiterator;
323  ::dataiterator_init_clone( _dip, rhs._dip );
324  }
325  }
326 
328  {
329  if ( _dip )
330  {
331  ::dataiterator_free( _dip );
332  delete _dip;
333  }
334  }
335 
336  std::ostream & operator<<( std::ostream & str, const DIWrap & obj )
337  { return str << obj.get(); }
338  }
339 
341  //
342  // CLASS NAME : LookupAttr::iterator
343  //
345 
347  // position and moving
349 
351  { return _dip ? Repository( _dip->repo ) : Repository::noRepository; }
352 
354  { return _dip ? Solvable( _dip->solvid ) : Solvable::noSolvable; }
355 
357  { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; }
358 
360  { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); }
361 
363  { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); }
364 
366  { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); }
367 
369  { if ( _dip ) { _dip.get()->repoid = -1; _dip.get()->flags |= SEARCH_THISSOLVID; } }
370 
372  { if ( _dip ) { _dip.get()->repoid = -1; } }
373 
375  // attr value type test
377 
379  { return _dip ? _dip->key->type : detail::noId; }
380 
382  {
383  switch ( solvAttrType() )
384  {
385  case REPOKEY_TYPE_U32:
386  case REPOKEY_TYPE_NUM:
387  case REPOKEY_TYPE_CONSTANT:
388  return true;
389  break;
390  }
391  return false;
392  }
393 
395  {
396  switch ( solvAttrType() )
397  {
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:
403  return true;
404  break;
405  }
406  return false;
407  }
408 
410  {
411  switch ( solvAttrType() )
412  {
413  case REPOKEY_TYPE_ID:
414  case REPOKEY_TYPE_IDARRAY:
415  case REPOKEY_TYPE_CONSTANTID:
416  return true;
417  break;
418  }
419  return false;
420  }
421 
423  {
424  switch ( solvAttrType() )
425  {
426  case REPOKEY_TYPE_MD5:
427  case REPOKEY_TYPE_SHA1:
428  case REPOKEY_TYPE_SHA256:
429  return true;
430  break;
431  }
432  return false;
433  }
434 
436  namespace
437  {
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 )
442  {
443  if ( ! dip )
444  return ST_NONE;
445  if ( dip.get()->key->type == REPOKEY_TYPE_FLEXARRAY )
446  return ST_FLEX;
447  return dip.get()->kv.parent ? ST_SUB : ST_NONE;
448  }
449  }
451 
453  { return subType( _dip ) != ST_NONE; }
454 
456  // Iterate sub-structures.
458 
460  { return( subBegin() == subEnd() ); }
461 
463  {
464  size_type c = 0;
465  for_( it, subBegin(), subEnd() )
466  ++c;
467  return c;
468  }
469 
471  {
472  SubType subtype( subType( _dip ) );
473  if ( subtype == ST_NONE )
474  return subEnd();
475  // setup the new sub iterator with the remembered position
476  detail::DIWrap dip( 0, 0, 0 );
477  ::dataiterator_clonepos( dip.get(), _dip.get() );
478  switch ( subtype )
479  {
480  case ST_NONE: // not reached
481  break;
482  case ST_FLEX:
483  ::dataiterator_seek( dip.get(), DI_SEEK_CHILD|DI_SEEK_STAY );
484  break;
485  case ST_SUB:
486  ::dataiterator_seek( dip.get(), DI_SEEK_REWIND|DI_SEEK_STAY );
487  break;
488  }
489  return iterator( dip ); // iterator takes over ownership!
490  }
491 
493  {
494  return iterator();
495  }
496 
498  {
499  iterator it = subBegin();
500  if ( attr_r != sat::SolvAttr::allAttr )
501  {
502  while ( it != subEnd() && it.inSolvAttr() != attr_r )
503  ++it;
504  }
505  return it;
506  }
507 
509  {
510  if ( attrname_r.empty() )
511  return subBegin();
512 
513  SubType subtype( subType( _dip ) );
514  if ( subtype == ST_NONE )
515  return subBegin();
516 
517  std::string subattr( inSolvAttr().asString() );
518  if ( subtype == ST_FLEX )
519  {
520  // append ":attrname"
521  subattr += ":";
522  subattr += attrname_r;
523  }
524  else
525  {
526  // replace "oldname" after ':' with "attrname"
527  std::string::size_type pos( subattr.rfind( ':' ) );
528  if ( pos != std::string::npos )
529  {
530  subattr.erase( pos+1 );
531  subattr += attrname_r;
532  }
533  else
534  subattr = attrname_r; // no ':' so replace all.
535  }
536  return subFind( SolvAttr( subattr ) );
537  }
538 
540  // attr value retrieval
542 
544  {
545  if ( _dip )
546  {
547  switch ( solvAttrType() )
548  {
549  case REPOKEY_TYPE_U32:
550  case REPOKEY_TYPE_NUM:
551  case REPOKEY_TYPE_CONSTANT:
552  return _dip->kv.num;
553  break;
554  }
555  }
556  return 0;
557  }
558 
560  { return asInt(); }
561 
562  unsigned long long LookupAttr::iterator::asUnsignedLL() const
563  {
564  if ( _dip )
565  {
566  switch ( solvAttrType() )
567  {
568  case REPOKEY_TYPE_U32:
569  case REPOKEY_TYPE_NUM:
570  case REPOKEY_TYPE_CONSTANT:
571  return SOLV_KV_NUM64(&_dip->kv);
572  break;
573  }
574  }
575  return 0;
576  }
577 
579  { return asInt(); }
580 
581 
582  const char * LookupAttr::iterator::c_str() const
583  {
584  if ( _dip )
585  {
586  switch ( solvAttrType() )
587  {
588  case REPOKEY_TYPE_ID:
589  case REPOKEY_TYPE_IDARRAY:
590  case REPOKEY_TYPE_CONSTANTID:
591  if ( _dip->data && _dip->data->localpool )
592  return ::stringpool_id2str( &_dip->data->spool, _dip->kv.id ); // in local pool
593  else
594  return IdString( _dip->kv.id ).c_str(); // in global pool
595  break;
596 
597  case REPOKEY_TYPE_STR:
598  return _dip->kv.str;
599  break;
600 
601  case REPOKEY_TYPE_DIRSTRARRAY:
602  return ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str );
603  break;
604  }
605  }
606  return 0;
607  }
608 
609  std::string LookupAttr::iterator::asString() const
610  {
611  if ( _dip )
612  {
613  switch ( solvAttrType() )
614  {
615  case REPOKEY_TYPE_ID:
616  case REPOKEY_TYPE_IDARRAY:
617  case REPOKEY_TYPE_CONSTANTID:
618  {
619  detail::IdType id = ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 );
620  return ISRELDEP(id) ? Capability( id ).asString()
621  : IdString( id ).asString();
622  }
623  break;
624 
625  case REPOKEY_TYPE_STR:
626  case REPOKEY_TYPE_DIRSTRARRAY:
627  {
628  const char * ret( c_str() );
629  return ret ? ret : "";
630  }
631  break;
632 
633  case REPOKEY_TYPE_U32:
634  case REPOKEY_TYPE_NUM:
635  case REPOKEY_TYPE_CONSTANT:
636  return str::numstring( asInt() );
637  break;
638 
639  case REPOKEY_TYPE_MD5:
640  case REPOKEY_TYPE_SHA1:
641  case REPOKEY_TYPE_SHA256:
642  {
643  return asCheckSum().asString();
644  }
645  break;
646 
647  case REPOKEY_TYPE_FLEXARRAY:
648  {
649  std::ostringstream str;
650  str << "{" << endl;
651  for_( it, subBegin(), subEnd() )
652  {
653  str << " " << it.inSolvAttr() << " = " << it.asString() << endl;
654  }
655  str << "}";
656  return str.str();
657  }
658  break;
659  }
660  }
661  return std::string();
662  }
663 
665  {
666  if ( _dip )
667  {
668  switch ( solvAttrType() )
669  {
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 ) );
674  break;
675  }
676  }
677  return IdString();
678  }
679 
681  {
682  if ( _dip )
683  {
684  switch ( solvAttrType() )
685  {
686  case REPOKEY_TYPE_MD5:
687  return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
688  break;
689 
690  case REPOKEY_TYPE_SHA1:
691  return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
692  break;
693 
694  case REPOKEY_TYPE_SHA256:
695  return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
696  break;
697  }
698  }
699  return CheckSum();
700  }
701 
703  // internal stuff below
705 
707  : iterator_adaptor_( 0 )
708  {}
709 
711  : iterator_adaptor_( 0 )
712  , _dip( rhs._dip )
713  {
714  base_reference() = _dip.get();
715  }
716 
718  : iterator_adaptor_( 0 )
719  {
720  _dip.swap( dip_r ); // take ownership!
721  base_reference() = _dip.get();
722  increment();
723  }
724 
726  {}
727 
729  {
730  if ( &rhs != this )
731  {
732  _dip = rhs._dip;
733  base_reference() = _dip.get();
734  }
735  return *this;
736  }
737 
739 
740  bool LookupAttr::iterator::dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const
741  {
742  // Iterator equal is same position in same container.
743  // Here: same attribute in same solvable.
744  return( lhs.solvid == rhs.solvid && lhs.key->name == rhs.key->name );
745  }
746 
748  {
749  return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 )
750  : detail::noId;
751  }
752 
754  {
755  if ( _dip && ! ::dataiterator_step( _dip.get() ) )
756  {
757  _dip.reset();
758  base_reference() = 0;
759  }
760  }
761 
762  std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
763  {
764  const ::_Dataiterator * dip = obj.get();
765  if ( ! dip )
766  return str << "EndOfQuery";
767 
768  if ( obj.inSolvable() )
769  str << obj.inSolvable();
770  else if ( obj.inRepo() )
771  str << obj.inRepo();
772 
773  str << '<' << obj.inSolvAttr() << (obj.solvAttrSubEntry() ? ">(*" : ">(")
774  << IdString(obj.solvAttrType()) << ") = " << obj.asString();
775  return str;
776  }
777 
778  template<> CheckSum LookupAttr::iterator::asType<CheckSum>() const
779  { return asCheckSum(); }
780 
782  } // namespace sat
785 } // namespace zypp
787 
788 std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj )
789 {
790  str << "::_Dataiterator(";
791  if ( ! obj )
792  {
793  str << "NULL";
794  }
795  else
796  {
797  str << "|" << zypp::Repository(obj->repo);
798  str << "|" << zypp::sat::Solvable(obj->solvid);
799  str << "|" << zypp::IdString(obj->key->name);
800  str << "|" << zypp::IdString(obj->key->type);
801  str << "|" << obj->repodataid;
802  str << "|" << obj->repoid;
803  }
804  return str << ")";
805 }
806