libzypp 8.13.6

Arch.cc

Go to the documentation of this file.
00001 /*---------------------------------------------------------------------\
00002 |                          ____ _   __ __ ___                          |
00003 |                         |__  / \ / / . \ . \                         |
00004 |                           / / \ V /|  _/  _/                         |
00005 |                          / /__ | | | | | |                           |
00006 |                         /_____||_| |_| |_|                           |
00007 |                                                                      |
00008 \---------------------------------------------------------------------*/
00012 #include <iostream>
00013 #include <list>
00014 #include <inttypes.h>
00015 
00016 #include "zypp/base/Logger.h"
00017 #include "zypp/base/Exception.h"
00018 #include "zypp/base/NonCopyable.h"
00019 #include "zypp/base/Tr1hash.h"
00020 #include "zypp/Arch.h"
00021 #include "zypp/Bit.h"
00022 
00023 using std::endl;
00024 
00026 namespace zypp
00027 { 
00028 
00030   //
00031   //    CLASS NAME : Arch::CompatEntry
00032   //
00038   struct Arch::CompatEntry
00039   {
00044     typedef bit::BitField<uint64_t> CompatBits;
00045 
00046     CompatEntry( const std::string & archStr_r,
00047                  CompatBits::IntT idBit_r = 1 )
00048     : _idStr( archStr_r )
00049     , _archStr( archStr_r )
00050     , _idBit( idBit_r )
00051     , _compatBits( idBit_r )
00052     {}
00053 
00054     CompatEntry( IdString archStr_r,
00055                  CompatBits::IntT idBit_r = 1 )
00056     : _idStr( archStr_r )
00057     , _archStr( archStr_r.asString() )
00058     , _idBit( idBit_r )
00059     , _compatBits( idBit_r )
00060     {}
00061 
00062     void addCompatBit( const CompatBits & idBit_r ) const
00063     {
00064       if ( idBit_r && ! (_compatBits & idBit_r) )
00065         {
00066           _compatBits |= idBit_r;
00067         }
00068     }
00069 
00071     bool compatibleWith( const CompatEntry & targetEntry_r ) const
00072     {
00073       switch ( _idBit.value() )
00074         {
00075         case 0:
00076           // this is noarch and always comatible
00077           return true;
00078           break;
00079         case 1:
00080           // this is a non builtin: self compatible only
00081           return _archStr == targetEntry_r._archStr;
00082           break;
00083         }
00084       // This is a builtin: compatible if mentioned in targetEntry_r
00085       return targetEntry_r._compatBits & _idBit;
00086     }
00087 
00089     int compare( const CompatEntry & rhs ) const
00090     {
00091       if ( _idBit.value() != rhs. _idBit.value() )
00092         return( _idBit.value() < rhs. _idBit.value() ? -1 : 1 );
00093       return _archStr.compare( rhs._archStr ); // Id 1: non builtin
00094     }
00095 
00096     bool isBuiltIn() const
00097     { return( _idBit != CompatBits(1) ); }
00098 
00099     IdString::IdType id() const
00100     { return _idStr.id(); }
00101 
00102     IdString            _idStr;
00103     std::string         _archStr; // frequently used by the UI so we keep a reference
00104     CompatBits          _idBit;
00105     mutable CompatBits  _compatBits;
00106   };
00108 
00110   inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
00111   {
00112     Arch::CompatEntry::CompatBits bit( obj._idBit );
00113     unsigned bitnum = 0;
00114     while ( bit )
00115     {
00116       ++bitnum;
00117       bit >>= 1;
00118     }
00119     return str << str::form( "%-15s ", obj._archStr.c_str() ) << str::numstring(bitnum,2) << ' '
00120                << obj._compatBits << ' ' << obj._compatBits.value();
00121   }
00122 
00124   inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
00125   { return lhs._idStr == rhs._idStr; }
00127   inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
00128   { return ! ( lhs == rhs ); }
00129 
00131 } // namespace zypp
00133 
00134 ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
00135 
00137 namespace zypp
00138 { 
00139 
00141   namespace
00142   { 
00143 
00144     // Builtin architecture STRING VALUES to be
00145     // used in defCompatibleWith below!
00146     //
00147     // const IdString  _foo( "foo" );
00148     //
00149     // NOTE: Builtin CLASS Arch CONSTANTS are defined below.
00150     //       You have to change them accordingly.
00151     //
00152     // NOTE: Thake care CompatBits::IntT is able to provide one
00153     //       bit for each architecture.
00154     //
00155 #define DEF_BUILTIN(A) const IdString  _##A( #A );
00156     DEF_BUILTIN( noarch );
00157 
00158     DEF_BUILTIN( i386 );
00159     DEF_BUILTIN( i486 );
00160     DEF_BUILTIN( i586 );
00161     DEF_BUILTIN( i686 );
00162     DEF_BUILTIN( athlon );
00163     DEF_BUILTIN( x86_64 );
00164 
00165     DEF_BUILTIN( pentium3 );
00166     DEF_BUILTIN( pentium4 );
00167 
00168     DEF_BUILTIN( s390 );
00169     DEF_BUILTIN( s390x );
00170 
00171     DEF_BUILTIN( ppc );
00172     DEF_BUILTIN( ppc64 );
00173 
00174     DEF_BUILTIN( ia64 );
00175 
00176     DEF_BUILTIN( alphaev67 );
00177     DEF_BUILTIN( alphaev6 );
00178     DEF_BUILTIN( alphapca56 );
00179     DEF_BUILTIN( alphaev56 );
00180     DEF_BUILTIN( alphaev5 );
00181     DEF_BUILTIN( alpha );
00182 
00183     DEF_BUILTIN( sparc64v );
00184     DEF_BUILTIN( sparcv9v );
00185     DEF_BUILTIN( sparc64 );
00186     DEF_BUILTIN( sparcv9 );
00187     DEF_BUILTIN( sparcv8 );
00188     DEF_BUILTIN( sparc );
00189 
00190     DEF_BUILTIN( armv7nhl );
00191     DEF_BUILTIN( armv7hl );
00192     DEF_BUILTIN( armv7l );
00193     DEF_BUILTIN( armv6l );
00194     DEF_BUILTIN( armv5tejl );
00195     DEF_BUILTIN( armv5tel );
00196     DEF_BUILTIN( armv5l );
00197     DEF_BUILTIN( armv4tl );
00198     DEF_BUILTIN( armv4l );
00199     DEF_BUILTIN( armv3l );
00200 
00201     DEF_BUILTIN( sh3 );
00202 
00203     DEF_BUILTIN( sh4 );
00204     DEF_BUILTIN( sh4a );
00205 #undef DEF_BUILTIN
00206 
00208     //
00209     //  CLASS NAME : CompatSet
00210     //
00218     struct ArchCompatSet : private base::NonCopyable
00219     {
00220       typedef Arch::CompatEntry       CompatEntry;
00221       typedef CompatEntry::CompatBits CompatBits;
00222 
00223       typedef std::tr1::unordered_set<CompatEntry> Set;
00224       typedef Set::iterator           iterator;
00225       typedef Set::const_iterator     const_iterator;
00226 
00228       static ArchCompatSet & instance()
00229       {
00230         static ArchCompatSet _instance;
00231         return _instance;
00232       }
00233 
00237       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
00238       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00240       const Arch::CompatEntry & assertDef( IdString archStr_r )
00241       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00242 
00243       const_iterator begin() const
00244       { return _compatSet.begin(); }
00245 
00246       const_iterator end() const
00247       { return _compatSet.end(); }
00248 
00249       struct DumpOnCompare
00250       {
00251         int operator()( const CompatEntry & lhs,  const CompatEntry & rhs ) const
00252         { return lhs._idBit.value() < rhs._idBit.value(); }
00253       };
00254 
00255       std::ostream & dumpOn( std::ostream & str ) const
00256       {
00257         str << "ArchCompatSet:";
00258         std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
00259         ov.sort( DumpOnCompare() );
00260         for_( it, ov.begin(), ov.end() )
00261           {
00262             str << endl << ' ' << *it;
00263           }
00264         return str;
00265       }
00266 
00267     private:
00269       ArchCompatSet()
00270       {
00271         // _noarch must have _idBit 0.
00272         // Other builtins have 1-bit set
00273         // and are initialized done on the fly.
00274         _compatSet.insert( Arch::CompatEntry( _noarch, 0 ) );
00276         // Define the CompatibleWith relation:
00277         //
00278         // NOTE: Order of definition is significant! (Arch::compare)
00279         //       - define compatible (less) architectures first!
00280         //
00281         defCompatibleWith( _i386,       _noarch );
00282         defCompatibleWith( _i486,       _noarch,_i386 );
00283         defCompatibleWith( _i586,       _noarch,_i386,_i486 );
00284         defCompatibleWith( _i686,       _noarch,_i386,_i486,_i586 );
00285         defCompatibleWith( _athlon,     _noarch,_i386,_i486,_i586,_i686 );
00286         defCompatibleWith( _x86_64,     _noarch,_i386,_i486,_i586,_i686,_athlon );
00287 
00288         defCompatibleWith( _pentium3,   _noarch,_i386,_i486,_i586,_i686 );
00289         defCompatibleWith( _pentium4,   _noarch,_i386,_i486,_i586,_i686,_pentium3 );
00290 
00291         defCompatibleWith( _ia64,       _noarch,_i386,_i486,_i586,_i686 );
00292         //
00293         defCompatibleWith( _s390,       _noarch );
00294         defCompatibleWith( _s390x,      _noarch,_s390 );
00295         //
00296         defCompatibleWith( _ppc,        _noarch );
00297         defCompatibleWith( _ppc64,      _noarch,_ppc );
00298         //
00299         defCompatibleWith( _alpha,      _noarch );
00300         defCompatibleWith( _alphaev5,   _noarch,_alpha );
00301         defCompatibleWith( _alphaev56,  _noarch,_alpha,_alphaev5 );
00302         defCompatibleWith( _alphapca56, _noarch,_alpha,_alphaev5,_alphaev56 );
00303         defCompatibleWith( _alphaev6,   _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56 );
00304         defCompatibleWith( _alphaev67,  _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56,_alphaev6 );
00305         //
00306         defCompatibleWith( _sparc,      _noarch );
00307         defCompatibleWith( _sparcv8,    _noarch,_sparc );
00308         defCompatibleWith( _sparcv9,    _noarch,_sparc,_sparcv8 );
00309         defCompatibleWith( _sparcv9v,   _noarch,_sparc,_sparcv8,_sparcv9 );
00310         //
00311         defCompatibleWith( _sparc64,    _noarch,_sparc,_sparcv8,_sparcv9 );
00312         defCompatibleWith( _sparc64v,   _noarch,_sparc,_sparcv8,_sparcv9,_sparcv9v,_sparc64 );
00313         //
00314         defCompatibleWith( _armv3l,     _noarch );
00315         defCompatibleWith( _armv4l,     _noarch,_armv3l );
00316         defCompatibleWith( _armv4tl,    _noarch,_armv3l,_armv4l );
00317         defCompatibleWith( _armv5l,     _noarch,_armv3l,_armv4l,_armv4tl );
00318         defCompatibleWith( _armv5tel,   _noarch,_armv3l,_armv4l,_armv4tl,_armv5l );
00319         defCompatibleWith( _armv5tejl,  _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel );
00320         defCompatibleWith( _armv6l,     _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl );
00321         defCompatibleWith( _armv7l,     _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl,_armv6l );
00322         defCompatibleWith( _armv7hl,    _noarch );
00323         defCompatibleWith( _armv7nhl,   _noarch, _armv7hl );
00324         //
00325         defCompatibleWith( _sh3,        _noarch );
00326         //
00327         defCompatibleWith( _sh4,        _noarch );
00328         defCompatibleWith( _sh4a,       _noarch,_sh4 );
00329         //
00331         // dumpOn( USR ) << endl;
00332       }
00333 
00334     private:
00340       CompatBits::IntT nextIdBit() const
00341       {
00342         if ( CompatBits::size == _compatSet.size() )
00343         {
00344           // Provide more bits in CompatBits::IntT
00345           INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
00346           ZYPP_THROW( Exception("Need more bits to encode architectures.") );
00347         }
00348         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
00349         return nextBit;
00350       }
00351 
00355       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
00356       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
00357 
00360       void defCompatibleWith( IdString targetArch_r,
00361                               IdString arch0_r,
00362                               IdString arch1_r = IdString(),
00363                               IdString arch2_r = IdString(),
00364                               IdString arch3_r = IdString(),
00365                               IdString arch4_r = IdString(),
00366                               IdString arch5_r = IdString(),
00367                               IdString arch6_r = IdString(),
00368                               IdString arch7_r = IdString(),
00369                               IdString arch8_r = IdString(),
00370                               IdString arch9_r = IdString() )
00371       {
00372         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
00373         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
00374 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
00375         _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
00376         _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
00377 #undef _SETARG
00378       }
00379 
00380     private:
00381       Set _compatSet;
00382     };
00383 
00385   } // namespace
00387 
00389   //
00390   //    CLASS NAME : Arch
00391   //
00393 
00394   const Arch Arch_empty ( IdString::Empty );
00395   const Arch Arch_noarch( _noarch );
00396 
00397   const Arch Arch_i386( _i386 );
00398   const Arch Arch_i486( _i486 );
00399   const Arch Arch_i586( _i586 );
00400   const Arch Arch_i686( _i686 );
00401   const Arch Arch_athlon( _athlon );
00402   const Arch Arch_x86_64( _x86_64 );
00403 
00404   const Arch Arch_pentium3( _pentium3 );
00405   const Arch Arch_pentium4( _pentium4 );
00406 
00407   const Arch Arch_s390( _s390 );
00408   const Arch Arch_s390x( _s390x );
00409 
00410   const Arch Arch_ppc( _ppc );
00411   const Arch Arch_ppc64( _ppc64 );
00412 
00413   const Arch Arch_ia64( _ia64 );
00414 
00415   const Arch Arch_alphaev67( _alphaev67 );
00416   const Arch Arch_alphaev6( _alphaev6 );
00417   const Arch Arch_alphapca56( _alphapca56 );
00418   const Arch Arch_alphaev56( _alphaev56 );
00419   const Arch Arch_alphaev5( _alphaev5 );
00420   const Arch Arch_alpha( _alpha );
00421 
00422   const Arch Arch_sparc64v( _sparc64v );
00423   const Arch Arch_sparc64( _sparc64 );
00424   const Arch Arch_sparcv9v( _sparcv9v );
00425   const Arch Arch_sparcv9( _sparcv9 );
00426   const Arch Arch_sparcv8( _sparcv8 );
00427   const Arch Arch_sparc( _sparc );
00428 
00429   const Arch Arch_armv7nhl ( _armv7nhl );
00430   const Arch Arch_armv7hl ( _armv7hl );
00431   const Arch Arch_armv7l( _armv7l );
00432   const Arch Arch_armv6l( _armv6l );
00433   const Arch Arch_armv5tejl( _armv5tejl );
00434   const Arch Arch_armv5tel( _armv5tel );
00435   const Arch Arch_armv5l( _armv5l );
00436   const Arch Arch_armv4tl( _armv4tl );
00437   const Arch Arch_armv4l( _armv4l );
00438   const Arch Arch_armv3l( _armv3l );
00439 
00440   const Arch Arch_sh3( _sh3 );
00441 
00442   const Arch Arch_sh4( _sh4 );
00443   const Arch Arch_sh4a( _sh4a );
00444 
00446   //
00447   //    METHOD NAME : Arch::Arch
00448   //    METHOD TYPE : Ctor
00449   //
00450   Arch::Arch()
00451   : _entry( &ArchCompatSet::instance().assertDef( _noarch ) )
00452   {}
00453 
00454   Arch::Arch( IdString::IdType id_r )
00455   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
00456   {}
00457 
00458   Arch::Arch( const IdString & idstr_r )
00459   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
00460   {}
00461 
00462   Arch::Arch( const std::string & str_r )
00463   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
00464   {}
00465 
00466   Arch::Arch( const char * cstr_r )
00467   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
00468   {}
00469 
00470   Arch::Arch( const CompatEntry & rhs )
00471   : _entry( &rhs )
00472   {}
00473 
00475   //
00476   //    METHOD NAME : Arch::idStr
00477   //    METHOD TYPE : IdString
00478   //
00479   IdString Arch::idStr() const
00480   { return _entry->_idStr; }
00481 
00483   //
00484   //    METHOD NAME : Arch::asString
00485   //    METHOD TYPE : const std::string &
00486   //
00487   const std::string & Arch::asString() const
00488   { return _entry->_archStr; }
00489 
00491   //
00492   //    METHOD NAME : Arch::isBuiltIn
00493   //    METHOD TYPE : bool
00494   //
00495   bool Arch::isBuiltIn() const
00496   { return _entry->isBuiltIn(); }
00497 
00499   //
00500   //    METHOD NAME : Arch::compatibleWith
00501   //    METHOD TYPE : bool
00502   //
00503   bool Arch::compatibleWith( const Arch & targetArch_r ) const
00504   { return _entry->compatibleWith( *targetArch_r._entry ); }
00505 
00507   //
00508   //    METHOD NAME : Arch::baseArch
00509   //    METHOD TYPE : Arch
00510   //
00511   Arch Arch::baseArch( ) const
00512   {
00513     // check the multilib archs:
00514     if (Arch_x86_64.compatibleWith(*this))
00515     {
00516       return Arch_x86_64;
00517     }
00518     if (Arch_sparc64v.compatibleWith(*this))
00519     {
00520       return Arch_sparc64v;
00521     }
00522     if (Arch_sparc64.compatibleWith(*this))
00523     {
00524       return Arch_sparc64;
00525     }
00526     if (Arch_ppc64.compatibleWith(*this))
00527     {
00528       return Arch_ppc64;
00529     }
00530     if (Arch_s390x.compatibleWith(*this))
00531     {
00532       return Arch_s390x;
00533     }
00534     // Here: no multilib; return arch before noarch
00535     CompatSet cset( compatSet( *this ) );
00536     if ( cset.size() > 2 )      // systemArchitecture, ..., basearch, noarch
00537     {
00538       return *(++cset.rbegin());
00539     }
00540     return *this;
00541   }
00542 
00544   //
00545   //    METHOD NAME : Arch::compare
00546   //    METHOD TYPE : bool
00547   //
00548   int Arch::compare( const Arch & rhs ) const
00549   { return _entry->compare( *rhs._entry ); }
00550 
00552   //
00553   //    METHOD NAME : Arch::compatSet
00554   //    METHOD TYPE : Arch::CompatSet
00555   //
00556   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
00557   {
00558     Arch::CompatSet ret;
00559 
00560     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
00561           it != ArchCompatSet::instance().end(); ++it )
00562       {
00563         if ( it->compatibleWith( *targetArch_r._entry ) )
00564           {
00565             ret.insert( Arch(*it) );
00566           }
00567       }
00568 
00569     return ret;
00570   }
00571 
00573 } // namespace zypp