libzypp  12.16.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  ::dataiterator_strdup( _dip );
325  }
326  }
327 
329  {
330  if ( _dip )
331  {
332  ::dataiterator_free( _dip );
333  delete _dip;
334  }
335  }
336 
337  std::ostream & operator<<( std::ostream & str, const DIWrap & obj )
338  { return str << obj.get(); }
339  }
340 
342  //
343  // CLASS NAME : LookupAttr::iterator
344  //
346 
348  // position and moving
350 
352  { return _dip ? Repository( _dip->repo ) : Repository::noRepository; }
353 
355  { return _dip ? Solvable( _dip->solvid ) : Solvable::noSolvable; }
356 
358  { return _dip ? SolvAttr( _dip->key->name ) : SolvAttr::noAttr; }
359 
361  { if ( _dip ) ::dataiterator_skip_attribute( _dip.get() ); }
362 
364  { if ( _dip ) ::dataiterator_skip_solvable( _dip.get() ); }
365 
367  { if ( _dip ) ::dataiterator_skip_repo( _dip.get() ); }
368 
370  { if ( _dip ) { _dip.get()->repoid = -1; _dip.get()->flags |= SEARCH_THISSOLVID; } }
371 
373  { if ( _dip ) { _dip.get()->repoid = -1; } }
374 
376  // attr value type test
378 
380  { return _dip ? _dip->key->type : detail::noId; }
381 
383  {
384  switch ( solvAttrType() )
385  {
386  case REPOKEY_TYPE_U32:
387  case REPOKEY_TYPE_NUM:
388  case REPOKEY_TYPE_CONSTANT:
389  return true;
390  break;
391  }
392  return false;
393  }
394 
396  {
397  switch ( solvAttrType() )
398  {
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:
404  return true;
405  break;
406  }
407  return false;
408  }
409 
411  {
412  switch ( solvAttrType() )
413  {
414  case REPOKEY_TYPE_ID:
415  case REPOKEY_TYPE_IDARRAY:
416  case REPOKEY_TYPE_CONSTANTID:
417  return true;
418  break;
419  }
420  return false;
421  }
422 
424  {
425  switch ( solvAttrType() )
426  {
427  case REPOKEY_TYPE_MD5:
428  case REPOKEY_TYPE_SHA1:
429  case REPOKEY_TYPE_SHA256:
430  return true;
431  break;
432  }
433  return false;
434  }
435 
437  namespace
438  {
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 )
443  {
444  if ( ! dip )
445  return ST_NONE;
446  if ( dip.get()->key->type == REPOKEY_TYPE_FLEXARRAY )
447  return ST_FLEX;
448  return dip.get()->kv.parent ? ST_SUB : ST_NONE;
449  }
450  }
452 
454  { return subType( _dip ) != ST_NONE; }
455 
457  // Iterate sub-structures.
459 
461  { return( subBegin() == subEnd() ); }
462 
464  {
465  size_type c = 0;
466  for_( it, subBegin(), subEnd() )
467  ++c;
468  return c;
469  }
470 
472  {
473  SubType subtype( subType( _dip ) );
474  if ( subtype == ST_NONE )
475  return subEnd();
476  // setup the new sub iterator with the remembered position
477  detail::DIWrap dip( 0, 0, 0 );
478  ::dataiterator_clonepos( dip.get(), _dip.get() );
479  switch ( subtype )
480  {
481  case ST_NONE: // not reached
482  break;
483  case ST_FLEX:
484  ::dataiterator_seek( dip.get(), DI_SEEK_CHILD|DI_SEEK_STAY );
485  break;
486  case ST_SUB:
487  ::dataiterator_seek( dip.get(), DI_SEEK_REWIND|DI_SEEK_STAY );
488  break;
489  }
490  return iterator( dip ); // iterator takes over ownership!
491  }
492 
494  {
495  return iterator();
496  }
497 
499  {
500  iterator it = subBegin();
501  if ( attr_r != sat::SolvAttr::allAttr )
502  {
503  while ( it != subEnd() && it.inSolvAttr() != attr_r )
504  ++it;
505  }
506  return it;
507  }
508 
510  {
511  if ( attrname_r.empty() )
512  return subBegin();
513 
514  SubType subtype( subType( _dip ) );
515  if ( subtype == ST_NONE )
516  return subBegin();
517 
518  std::string subattr( inSolvAttr().asString() );
519  if ( subtype == ST_FLEX )
520  {
521  // append ":attrname"
522  subattr += ":";
523  subattr += attrname_r;
524  }
525  else
526  {
527  // replace "oldname" after ':' with "attrname"
528  std::string::size_type pos( subattr.rfind( ':' ) );
529  if ( pos != std::string::npos )
530  {
531  subattr.erase( pos+1 );
532  subattr += attrname_r;
533  }
534  else
535  subattr = attrname_r; // no ':' so replace all.
536  }
537  return subFind( SolvAttr( subattr ) );
538  }
539 
541  // attr value retrieval
543 
545  {
546  if ( _dip )
547  {
548  switch ( solvAttrType() )
549  {
550  case REPOKEY_TYPE_U32:
551  case REPOKEY_TYPE_NUM:
552  case REPOKEY_TYPE_CONSTANT:
553  return _dip->kv.num;
554  break;
555  }
556  }
557  return 0;
558  }
559 
561  { return asInt(); }
562 
563  unsigned long long LookupAttr::iterator::asUnsignedLL() const
564  {
565  if ( _dip )
566  {
567  switch ( solvAttrType() )
568  {
569  case REPOKEY_TYPE_U32:
570  case REPOKEY_TYPE_NUM:
571  case REPOKEY_TYPE_CONSTANT:
572  return SOLV_KV_NUM64(&_dip->kv);
573  break;
574  }
575  }
576  return 0;
577  }
578 
580  { return asInt(); }
581 
582 
583  const char * LookupAttr::iterator::c_str() const
584  {
585  if ( _dip )
586  {
587  switch ( solvAttrType() )
588  {
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
594  else
595  return IdString( _dip->kv.id ).c_str(); // in global pool
596  break;
597 
598  case REPOKEY_TYPE_STR:
599  return _dip->kv.str;
600  break;
601 
602  case REPOKEY_TYPE_DIRSTRARRAY:
603  // may or may not be stringified depending on SEARCH_FILES flag
604  return( _dip->flags & SEARCH_FILES
605  ? _dip->kv.str
606  : ::repodata_dir2str( _dip->data, _dip->kv.id, _dip->kv.str ) );
607  break;
608  }
609  }
610  return 0;
611  }
612 
613  std::string LookupAttr::iterator::asString() const
614  {
615  if ( _dip )
616  {
617  switch ( solvAttrType() )
618  {
619  case REPOKEY_TYPE_ID:
620  case REPOKEY_TYPE_IDARRAY:
621  case REPOKEY_TYPE_CONSTANTID:
622  {
623  detail::IdType id = ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 );
624  return ISRELDEP(id) ? Capability( id ).asString()
625  : IdString( id ).asString();
626  }
627  break;
628 
629  case REPOKEY_TYPE_STR:
630  case REPOKEY_TYPE_DIRSTRARRAY:
631  {
632  const char * ret( c_str() );
633  return ret ? ret : "";
634  }
635  break;
636 
637  case REPOKEY_TYPE_U32:
638  case REPOKEY_TYPE_NUM:
639  case REPOKEY_TYPE_CONSTANT:
640  return str::numstring( asInt() );
641  break;
642 
643  case REPOKEY_TYPE_MD5:
644  case REPOKEY_TYPE_SHA1:
645  case REPOKEY_TYPE_SHA256:
646  {
647  return asCheckSum().asString();
648  }
649  break;
650 
651  case REPOKEY_TYPE_FLEXARRAY:
652  {
653  std::ostringstream str;
654  str << "{" << endl;
655  for_( it, subBegin(), subEnd() )
656  {
657  str << " " << it.inSolvAttr() << " = " << it.asString() << endl;
658  }
659  str << "}";
660  return str.str();
661  }
662  break;
663  }
664  }
665  return std::string();
666  }
667 
669  {
670  if ( _dip )
671  {
672  switch ( solvAttrType() )
673  {
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 ) );
678  break;
679  }
680  }
681  return IdString();
682  }
683 
685  {
686  if ( _dip )
687  {
688  switch ( solvAttrType() )
689  {
690  case REPOKEY_TYPE_MD5:
691  return CheckSum::md5( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
692  break;
693 
694  case REPOKEY_TYPE_SHA1:
695  return CheckSum::sha1( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
696  break;
697 
698  case REPOKEY_TYPE_SHA256:
699  return CheckSum::sha256( ::repodata_chk2str( _dip->data, solvAttrType(), (unsigned char *)_dip->kv.str ) );
700  break;
701  }
702  }
703  return CheckSum();
704  }
705 
707  // internal stuff below
709 
711  : iterator_adaptor_( 0 )
712  {}
713 
715  : iterator_adaptor_( 0 )
716  , _dip( rhs._dip )
717  {
718  base_reference() = _dip.get();
719  }
720 
722  : iterator_adaptor_( 0 )
723  {
724  _dip.swap( dip_r ); // take ownership!
725  base_reference() = _dip.get();
726  increment();
727  }
728 
730  {}
731 
733  {
734  if ( &rhs != this )
735  {
736  _dip = rhs._dip;
737  base_reference() = _dip.get();
738  }
739  return *this;
740  }
741 
743 
744  bool LookupAttr::iterator::dip_equal( const ::_Dataiterator & lhs, const ::_Dataiterator & rhs ) const
745  {
746  // Iterator equal is same position in same container.
747  // Here: same attribute in same solvable.
748  return( lhs.solvid == rhs.solvid && lhs.key->name == rhs.key->name );
749  }
750 
752  {
753  return _dip ? ::repodata_globalize_id( _dip->data, _dip->kv.id, 1 )
754  : detail::noId;
755  }
756 
758  {
759  if ( _dip )
760  {
761  if ( ! ::dataiterator_step( _dip.get() ) )
762  {
763  _dip.reset();
764  base_reference() = 0;
765  }
766  else
767  {
768  ::dataiterator_strdup( _dip.get() );
769  }
770  }
771  }
772 
773  std::ostream & operator<<( std::ostream & str, const LookupAttr::iterator & obj )
774  {
775  const ::_Dataiterator * dip = obj.get();
776  if ( ! dip )
777  return str << "EndOfQuery";
778 
779  if ( obj.inSolvable() )
780  str << obj.inSolvable();
781  else if ( obj.inRepo() )
782  str << obj.inRepo();
783 
784  str << '<' << obj.inSolvAttr() << (obj.solvAttrSubEntry() ? ">(*" : ">(")
785  << IdString(obj.solvAttrType()) << ") = " << obj.asString();
786  return str;
787  }
788 
789  template<> CheckSum LookupAttr::iterator::asType<CheckSum>() const
790  { return asCheckSum(); }
791 
793  } // namespace sat
796 } // namespace zypp
798 
799 std::ostream & operator<<( std::ostream & str, const ::_Dataiterator * obj )
800 {
801  str << "::_Dataiterator(";
802  if ( ! obj )
803  {
804  str << "NULL";
805  }
806  else
807  {
808  str << "|" << zypp::Repository(obj->repo);
809  str << "|" << zypp::sat::Solvable(obj->solvid);
810  str << "|" << zypp::IdString(obj->key->name);
811  str << "|" << zypp::IdString(obj->key->type);
812  str << "|" << obj->repodataid;
813  str << "|" << obj->repoid;
814  }
815  return str << ")";
816 }
817