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     , _compatScore( idBit_r ? 1 : 0 ) // number of compatible archs
00053     {}
00054 
00055     CompatEntry( IdString archStr_r,
00056                  CompatBits::IntT idBit_r = 1 )
00057     : _idStr( archStr_r )
00058     , _archStr( archStr_r.asString() )
00059     , _idBit( idBit_r )
00060     , _compatBits( idBit_r )
00061     , _compatScore( idBit_r ? 1 : 0 ) // number of compatible archs
00062     {}
00063 
00064     void addCompatBit( const CompatBits & idBit_r ) const
00065     {
00066       if ( idBit_r && ! (_compatBits & idBit_r) )
00067         {
00068           _compatBits |= idBit_r;
00069           ++_compatScore;
00070         }
00071     }
00072 
00074     bool compatibleWith( const CompatEntry & targetEntry_r ) const
00075     {
00076       switch ( _idBit.value() )
00077         {
00078         case 0:
00079           // this is noarch and always comatible
00080           return true;
00081           break;
00082         case 1:
00083           // this is a non builtin: self compatible only
00084           return _archStr == targetEntry_r._archStr;
00085           break;
00086         }
00087       // This is a builtin: compatible if mentioned in targetEntry_r
00088       return targetEntry_r._compatBits & _idBit;
00089     }
00090 
00092     int compare( const CompatEntry & rhs ) const
00093     {
00094       if ( _compatScore != rhs._compatScore )
00095         return( _compatScore < rhs._compatScore ? -1 : 1 );
00096       return _archStr.compare( rhs._archStr );
00097     }
00098 
00099     bool isBuiltIn() const
00100     { return( _idBit != CompatBits(1) ); }
00101 
00102     IdString::IdType id() const
00103     { return _idStr.id(); }
00104 
00105     IdString            _idStr;
00106     std::string         _archStr; // frequently used by the UI so we keep a reference
00107     CompatBits          _idBit;
00108     mutable CompatBits  _compatBits;
00109     mutable unsigned    _compatScore;
00110   };
00112 
00114   inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
00115   {
00116     Arch::CompatEntry::CompatBits bit( obj._idBit );
00117     unsigned bitnum = 0;
00118     while ( bit )
00119     {
00120       ++bitnum;
00121       bit >>= 1;
00122     }
00123     return str << str::form( "%-15s ", obj._archStr.c_str() ) << str::numstring(bitnum,2) << ' '
00124                << obj._compatBits << ' ' << obj._compatScore;
00125   }
00126 
00128   inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
00129   { return lhs._idStr == rhs._idStr; }
00131   inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
00132   { return ! ( lhs == rhs ); }
00133 
00135 } // namespace zypp
00137 
00138 ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
00139 
00141 namespace zypp
00142 { 
00143 
00145   namespace
00146   { 
00147 
00148     // Builtin architecture STRING VALUES to be
00149     // used in defCompatibleWith below!
00150     //
00151     // const IdString  _foo( "foo" );
00152     //
00153     // NOTE: Builtin CLASS Arch CONSTANTS are defined below.
00154     //       You have to change them accordingly.
00155     //
00156     // NOTE: Thake care CompatBits::IntT is able to provide one
00157     //       bit for each architectue.
00158     //
00159 #define DEF_BUILTIN(A) const IdString  _##A( #A );
00160     DEF_BUILTIN( noarch );
00161 
00162     DEF_BUILTIN( i386 );
00163     DEF_BUILTIN( i486 );
00164     DEF_BUILTIN( i586 );
00165     DEF_BUILTIN( i686 );
00166     DEF_BUILTIN( athlon );
00167     DEF_BUILTIN( x86_64 );
00168 
00169     DEF_BUILTIN( pentium3 );
00170     DEF_BUILTIN( pentium4 );
00171 
00172     DEF_BUILTIN( s390 );
00173     DEF_BUILTIN( s390x );
00174 
00175     DEF_BUILTIN( ppc );
00176     DEF_BUILTIN( ppc64 );
00177 
00178     DEF_BUILTIN( ia64 );
00179 
00180     DEF_BUILTIN( alphaev67 );
00181     DEF_BUILTIN( alphaev6 );
00182     DEF_BUILTIN( alphapca56 );
00183     DEF_BUILTIN( alphaev56 );
00184     DEF_BUILTIN( alphaev5 );
00185     DEF_BUILTIN( alpha );
00186 
00187     DEF_BUILTIN( sparc64v );
00188     DEF_BUILTIN( sparcv9v );
00189     DEF_BUILTIN( sparc64 );
00190     DEF_BUILTIN( sparcv9 );
00191     DEF_BUILTIN( sparcv8 );
00192     DEF_BUILTIN( sparc );
00193 
00194     DEF_BUILTIN( armv7l );
00195     DEF_BUILTIN( armv6l );
00196     DEF_BUILTIN( armv5tejl );
00197     DEF_BUILTIN( armv5tel );
00198     DEF_BUILTIN( armv5l );
00199     DEF_BUILTIN( armv4tl );
00200     DEF_BUILTIN( armv4l );
00201     DEF_BUILTIN( armv3l );
00202 
00203     DEF_BUILTIN( sh3 );
00204 
00205     DEF_BUILTIN( sh4 );
00206     DEF_BUILTIN( sh4a );
00207 #undef DEF_BUILTIN
00208 
00210     //
00211     //  CLASS NAME : CompatSet
00212     //
00220     struct ArchCompatSet : private base::NonCopyable
00221     {
00222       typedef Arch::CompatEntry       CompatEntry;
00223       typedef CompatEntry::CompatBits CompatBits;
00224 
00225       typedef std::tr1::unordered_set<CompatEntry> Set;
00226       typedef Set::iterator           iterator;
00227       typedef Set::const_iterator     const_iterator;
00228 
00230       static ArchCompatSet & instance()
00231       {
00232         static ArchCompatSet _instance;
00233         return _instance;
00234       }
00235 
00239       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
00240       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00242       const Arch::CompatEntry & assertDef( IdString archStr_r )
00243       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
00244 
00245       const_iterator begin() const
00246       { return _compatSet.begin(); }
00247 
00248       const_iterator end() const
00249       { return _compatSet.end(); }
00250 
00251       struct DumpOnCompare
00252       {
00253         int operator()( const CompatEntry & lhs,  const CompatEntry & rhs ) const
00254         { return lhs._idBit.value() < rhs._idBit.value(); }
00255       };
00256 
00257       std::ostream & dumpOn( std::ostream & str ) const
00258       {
00259         str << "ArchCompatSet:";
00260         std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
00261         ov.sort( DumpOnCompare() );
00262         for_( it, ov.begin(), ov.end() )
00263           {
00264             str << endl << ' ' << *it;
00265           }
00266         return str;
00267       }
00268 
00269     private:
00271       ArchCompatSet()
00272       {
00273         // _noarch must have _idBit 0.
00274         // Other builtins have 1-bit set
00275         // and are initialized done on the fly.
00276         _compatSet.insert( Arch::CompatEntry( _noarch, 0 ) );
00278         // Define the CompatibleWith relation:
00279         //
00280         defCompatibleWith( _i386,       _noarch );
00281         defCompatibleWith( _i486,       _noarch,_i386 );
00282         defCompatibleWith( _i586,       _noarch,_i386,_i486 );
00283         defCompatibleWith( _i686,       _noarch,_i386,_i486,_i586 );
00284         defCompatibleWith( _athlon,     _noarch,_i386,_i486,_i586,_i686 );
00285         defCompatibleWith( _x86_64,     _noarch,_i386,_i486,_i586,_i686,_athlon );
00286 
00287         defCompatibleWith( _pentium3,   _noarch,_i386,_i486,_i586,_i686 );
00288         defCompatibleWith( _pentium4,   _noarch,_i386,_i486,_i586,_i686,_pentium3 );
00289 
00290         defCompatibleWith( _ia64,       _noarch,_i386,_i486,_i586,_i686 );
00291         //
00292         defCompatibleWith( _s390,       _noarch );
00293         defCompatibleWith( _s390x,      _noarch,_s390 );
00294         //
00295         defCompatibleWith( _ppc,        _noarch );
00296         defCompatibleWith( _ppc64,      _noarch,_ppc );
00297         //
00298         defCompatibleWith( _alpha,      _noarch );
00299         defCompatibleWith( _alphaev5,   _noarch,_alpha );
00300         defCompatibleWith( _alphaev56,  _noarch,_alpha,_alphaev5 );
00301         defCompatibleWith( _alphapca56, _noarch,_alpha,_alphaev5,_alphaev56 );
00302         defCompatibleWith( _alphaev6,   _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56 );
00303         defCompatibleWith( _alphaev67,  _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56,_alphaev6 );
00304         //
00305         defCompatibleWith( _sparc,      _noarch );
00306         defCompatibleWith( _sparcv8,    _noarch,_sparc );
00307         defCompatibleWith( _sparcv9,    _noarch,_sparc,_sparcv8 );
00308         defCompatibleWith( _sparc64,    _noarch,_sparc,_sparcv8,_sparcv9 );
00309         //
00310         defCompatibleWith( _sparcv9v,   _noarch,_sparc,_sparcv8,_sparcv9 );
00311         defCompatibleWith( _sparc64v,   _noarch,_sparc,_sparcv8,_sparcv9,_sparcv9v,_sparc64 );
00312         //
00313         defCompatibleWith( _armv3l,     _noarch );
00314         defCompatibleWith( _armv4l,     _noarch,_armv3l );
00315         defCompatibleWith( _armv4tl,    _noarch,_armv3l,_armv4l );
00316         defCompatibleWith( _armv5l,     _noarch,_armv3l,_armv4l,_armv4tl );
00317         defCompatibleWith( _armv5tel,   _noarch,_armv3l,_armv4l,_armv4tl,_armv5l );
00318         defCompatibleWith( _armv5tejl,  _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel );
00319         defCompatibleWith( _armv6l,     _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl );
00320         defCompatibleWith( _armv7l,     _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl,_armv6l );
00321         //
00322         defCompatibleWith( _sh3,        _noarch );
00323         //
00324         defCompatibleWith( _sh4,        _noarch );
00325         defCompatibleWith( _sh4a,       _noarch,_sh4 );
00326         //
00328         // dumpOn( USR ) << endl;
00329       }
00330 
00331     private:
00337       CompatBits::IntT nextIdBit() const
00338       {
00339         if ( CompatBits::size == _compatSet.size() )
00340         {
00341           // Provide more bits in CompatBits::IntT
00342           INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
00343           ZYPP_THROW( Exception("Need more bits to encode architectures.") );
00344         }
00345         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
00346         return nextBit;
00347       }
00348 
00352       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
00353       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
00354 
00357       void defCompatibleWith( IdString targetArch_r,
00358                               IdString arch0_r,
00359                               IdString arch1_r = IdString(),
00360                               IdString arch2_r = IdString(),
00361                               IdString arch3_r = IdString(),
00362                               IdString arch4_r = IdString(),
00363                               IdString arch5_r = IdString(),
00364                               IdString arch6_r = IdString(),
00365                               IdString arch7_r = IdString(),
00366                               IdString arch8_r = IdString(),
00367                               IdString arch9_r = IdString() )
00368       {
00369         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
00370         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
00371 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
00372         _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
00373         _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
00374 #undef _SETARG
00375       }
00376 
00377     private:
00378       Set _compatSet;
00379     };
00380 
00382   } // namespace
00384 
00386   //
00387   //    CLASS NAME : Arch
00388   //
00390 
00391   const Arch Arch_empty ( IdString::Empty );
00392   const Arch Arch_noarch( _noarch );
00393 
00394   const Arch Arch_i386( _i386 );
00395   const Arch Arch_i486( _i486 );
00396   const Arch Arch_i586( _i586 );
00397   const Arch Arch_i686( _i686 );
00398   const Arch Arch_athlon( _athlon );
00399   const Arch Arch_x86_64( _x86_64 );
00400 
00401   const Arch Arch_pentium3( _pentium3 );
00402   const Arch Arch_pentium4( _pentium4 );
00403 
00404   const Arch Arch_s390( _s390 );
00405   const Arch Arch_s390x( _s390x );
00406 
00407   const Arch Arch_ppc( _ppc );
00408   const Arch Arch_ppc64( _ppc64 );
00409 
00410   const Arch Arch_ia64( _ia64 );
00411 
00412   const Arch Arch_alphaev67( _alphaev67 );
00413   const Arch Arch_alphaev6( _alphaev6 );
00414   const Arch Arch_alphapca56( _alphapca56 );
00415   const Arch Arch_alphaev56( _alphaev56 );
00416   const Arch Arch_alphaev5( _alphaev5 );
00417   const Arch Arch_alpha( _alpha );
00418 
00419   const Arch Arch_sparc64v( _sparc64v );
00420   const Arch Arch_sparcv9v( _sparcv9v );
00421   const Arch Arch_sparc64( _sparc64 );
00422   const Arch Arch_sparcv9( _sparcv9 );
00423   const Arch Arch_sparcv8( _sparcv8 );
00424   const Arch Arch_sparc( _sparc );
00425 
00426   const Arch Arch_armv7l( _armv7l );
00427   const Arch Arch_armv6l( _armv6l );
00428   const Arch Arch_armv5tejl( _armv5tejl );
00429   const Arch Arch_armv5tel( _armv5tel );
00430   const Arch Arch_armv5l( _armv5l );
00431   const Arch Arch_armv4tl( _armv4tl );
00432   const Arch Arch_armv4l( _armv4l );
00433   const Arch Arch_armv3l( _armv3l );
00434 
00435   const Arch Arch_sh3( _sh3 );
00436 
00437   const Arch Arch_sh4( _sh4 );
00438   const Arch Arch_sh4a( _sh4a );
00439 
00441   //
00442   //    METHOD NAME : Arch::Arch
00443   //    METHOD TYPE : Ctor
00444   //
00445   Arch::Arch()
00446   : _entry( &ArchCompatSet::instance().assertDef( _noarch ) )
00447   {}
00448 
00449   Arch::Arch( IdString::IdType id_r )
00450   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
00451   {}
00452 
00453   Arch::Arch( const IdString & idstr_r )
00454   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
00455   {}
00456 
00457   Arch::Arch( const std::string & str_r )
00458   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
00459   {}
00460 
00461   Arch::Arch( const char * cstr_r )
00462   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
00463   {}
00464 
00465   Arch::Arch( const CompatEntry & rhs )
00466   : _entry( &rhs )
00467   {}
00468 
00470   //
00471   //    METHOD NAME : Arch::idStr
00472   //    METHOD TYPE : IdString
00473   //
00474   IdString Arch::idStr() const
00475   { return _entry->_idStr; }
00476 
00478   //
00479   //    METHOD NAME : Arch::asString
00480   //    METHOD TYPE : const std::string &
00481   //
00482   const std::string & Arch::asString() const
00483   { return _entry->_archStr; }
00484 
00486   //
00487   //    METHOD NAME : Arch::isBuiltIn
00488   //    METHOD TYPE : bool
00489   //
00490   bool Arch::isBuiltIn() const
00491   { return _entry->isBuiltIn(); }
00492 
00494   //
00495   //    METHOD NAME : Arch::compatibleWith
00496   //    METHOD TYPE : bool
00497   //
00498   bool Arch::compatibleWith( const Arch & targetArch_r ) const
00499   { return _entry->compatibleWith( *targetArch_r._entry ); }
00500 
00502   //
00503   //    METHOD NAME : Arch::compare
00504   //    METHOD TYPE : bool
00505   //
00506   int Arch::compare( const Arch & rhs ) const
00507   { return _entry->compare( *rhs._entry ); }
00508 
00510   //
00511   //    METHOD NAME : Arch::compatSet
00512   //    METHOD TYPE : Arch::CompatSet
00513   //
00514   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
00515   {
00516     Arch::CompatSet ret;
00517 
00518     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
00519           it != ArchCompatSet::instance().end(); ++it )
00520       {
00521         if ( it->compatibleWith( *targetArch_r._entry ) )
00522           {
00523             ret.insert( Arch(*it) );
00524           }
00525       }
00526 
00527     return ret;
00528   }
00529 
00531 } // namespace zypp

doxygen