Imported Upstream version 15.0.0
[platform/upstream/libzypp.git] / zypp / Arch.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/Arch.cc
10  *
11 */
12 #include <iostream>
13 #include <list>
14 #include <inttypes.h>
15
16 #include "zypp/base/Logger.h"
17 #include "zypp/base/Exception.h"
18 #include "zypp/base/NonCopyable.h"
19 #include "zypp/base/Tr1hash.h"
20 #include "zypp/Arch.h"
21 #include "zypp/Bit.h"
22
23 using std::endl;
24
25 ///////////////////////////////////////////////////////////////////
26 namespace zypp
27 { /////////////////////////////////////////////////////////////////
28
29   ///////////////////////////////////////////////////////////////////
30   //
31   //    CLASS NAME : Arch::CompatEntry
32   //
33   /** Holds an architecture ID and it's compatible relation.
34    * An architecture is compatibleWith, if it's _idBit is set in
35    * _compatBits. noarch has ID 0, non builtin archs ID 1 and
36    * have to be treated specialy.
37   */
38   struct Arch::CompatEntry
39   {
40     /** Bitfield for architecture IDs and compatBits relation.
41      * \note Need one bit for each builtin Arch.
42      * \todo Migrate to some infinite BitField
43     */
44     typedef bit::BitField<uint64_t> CompatBits;
45
46     CompatEntry( const std::string & archStr_r,
47                  CompatBits::IntT idBit_r = 1 )
48     : _idStr( archStr_r )
49     , _archStr( archStr_r )
50     , _idBit( idBit_r )
51     , _compatBits( idBit_r )
52     {}
53
54     CompatEntry( IdString archStr_r,
55                  CompatBits::IntT idBit_r = 1 )
56     : _idStr( archStr_r )
57     , _archStr( archStr_r.asString() )
58     , _idBit( idBit_r )
59     , _compatBits( idBit_r )
60     {}
61
62     void addCompatBit( const CompatBits & idBit_r ) const
63     {
64       if ( idBit_r && ! (_compatBits & idBit_r) )
65         {
66           _compatBits |= idBit_r;
67         }
68     }
69
70     /** Return whether \c this is compatible with \a targetEntry_r.*/
71     bool compatibleWith( const CompatEntry & targetEntry_r ) const
72     {
73       switch ( _idBit.value() )
74         {
75         case 0:
76           // this is noarch and always comatible
77           return true;
78           break;
79         case 1:
80           // this is a non builtin: self compatible only
81           return _archStr == targetEntry_r._archStr;
82           break;
83         }
84       // This is a builtin: compatible if mentioned in targetEntry_r
85       return bool( targetEntry_r._compatBits & _idBit );
86     }
87
88     /** compare by score, then archStr. */
89     int compare( const CompatEntry & rhs ) const
90     {
91       if ( _idBit.value() != rhs. _idBit.value() )
92         return( _idBit.value() < rhs. _idBit.value() ? -1 : 1 );
93       return _archStr.compare( rhs._archStr ); // Id 1: non builtin
94     }
95
96     bool isBuiltIn() const
97     { return( _idBit != CompatBits(1) ); }
98
99     IdString::IdType id() const
100     { return _idStr.id(); }
101
102     IdString            _idStr;
103     std::string         _archStr; // frequently used by the UI so we keep a reference
104     CompatBits          _idBit;
105     mutable CompatBits  _compatBits;
106   };
107   ///////////////////////////////////////////////////////////////////
108
109   /** \relates Arch::CompatEntry Stream output */
110   inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
111   {
112     Arch::CompatEntry::CompatBits bit( obj._idBit );
113     unsigned bitnum = 0;
114     while ( bit )
115     {
116       ++bitnum;
117       bit >>= 1;
118     }
119     return str << str::form( "%-15s ", obj._archStr.c_str() ) << str::numstring(bitnum,2) << ' '
120                << obj._compatBits << ' ' << obj._compatBits.value();
121   }
122
123   /** \relates Arch::CompatEntry */
124   inline bool operator==( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
125   { return lhs._idStr == rhs._idStr; }
126   /** \relates Arch::CompatEntry */
127   inline bool operator!=( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
128   { return ! ( lhs == rhs ); }
129
130   /////////////////////////////////////////////////////////////////
131 } // namespace zypp
132 ///////////////////////////////////////////////////////////////////
133
134 ZYPP_DEFINE_ID_HASHABLE( zypp::Arch::CompatEntry );
135
136 ///////////////////////////////////////////////////////////////////
137 namespace zypp
138 { /////////////////////////////////////////////////////////////////
139
140   // Builtin architecture STRING VALUES to be
141   // used in defCompatibleWith below!
142   //
143   // const IdString  _foo( "foo" );
144   // const Arch Arch_foo( _foo() );
145   //
146   // NOTE: Builtin CLASS Arch CONSTANTS are defined below.
147   //       You have to change them accordingly in Arch.h.
148   //
149   // NOTE: Thake care CompatBits::IntT is able to provide one
150   //       bit for each architecture.
151   //
152   #define DEF_BUILTIN(A) \
153   namespace { static inline const IdString & _##A () { static IdString __str(#A); return __str; } } \
154   const Arch Arch_##A( _##A() )
155
156   DEF_BUILTIN( noarch );
157
158   DEF_BUILTIN( i386 );
159   DEF_BUILTIN( i486 );
160   DEF_BUILTIN( i586 );
161   DEF_BUILTIN( i686 );
162   DEF_BUILTIN( athlon );
163   DEF_BUILTIN( x86_64 );
164
165   DEF_BUILTIN( pentium3 );
166   DEF_BUILTIN( pentium4 );
167
168   DEF_BUILTIN( s390 );
169   DEF_BUILTIN( s390x );
170
171   DEF_BUILTIN( ppc );
172   DEF_BUILTIN( ppc64 );
173   DEF_BUILTIN( ppc64p7 );
174
175   DEF_BUILTIN( ppc64le );
176
177   DEF_BUILTIN( ia64 );
178
179   DEF_BUILTIN( alphaev67 );
180   DEF_BUILTIN( alphaev6 );
181   DEF_BUILTIN( alphapca56 );
182   DEF_BUILTIN( alphaev56 );
183   DEF_BUILTIN( alphaev5 );
184   DEF_BUILTIN( alpha );
185
186   DEF_BUILTIN( sparc64v );
187   DEF_BUILTIN( sparcv9v );
188   DEF_BUILTIN( sparc64 );
189   DEF_BUILTIN( sparcv9 );
190   DEF_BUILTIN( sparcv8 );
191   DEF_BUILTIN( sparc );
192
193   DEF_BUILTIN( aarch64 );
194   DEF_BUILTIN( armv7tnhl );
195   DEF_BUILTIN( armv7thl );
196   DEF_BUILTIN( armv7nhl );
197   DEF_BUILTIN( armv7hl );
198   DEF_BUILTIN( armv7l );
199   DEF_BUILTIN( armv6hl );
200   DEF_BUILTIN( armv6l );
201   DEF_BUILTIN( armv5tejl );
202   DEF_BUILTIN( armv5tel );
203   DEF_BUILTIN( armv5l );
204   DEF_BUILTIN( armv4tl );
205   DEF_BUILTIN( armv4l );
206   DEF_BUILTIN( armv3l );
207
208   DEF_BUILTIN( sh3 );
209
210   DEF_BUILTIN( sh4 );
211   DEF_BUILTIN( sh4a );
212
213   DEF_BUILTIN(m68k);
214 #undef DEF_BUILTIN
215
216   ///////////////////////////////////////////////////////////////////
217   namespace
218   { /////////////////////////////////////////////////////////////////
219
220     ///////////////////////////////////////////////////////////////////
221     //
222     //  CLASS NAME : CompatSet
223     //
224     /** Maintain architecture compatibility (Singleton by the way it is used).
225      *
226      * Povides \ref Arch::CompatEntry for \ref Arch. Defines the
227      * compatibleWith relation.
228      * \li \c noarch has _idBit 0
229      * \li \c nonbuiltin archs have _idBit 1
230     */
231     struct ArchCompatSet : private base::NonCopyable
232     {
233       typedef Arch::CompatEntry       CompatEntry;
234       typedef CompatEntry::CompatBits CompatBits;
235
236       typedef std::tr1::unordered_set<CompatEntry> Set;
237       typedef Set::iterator           iterator;
238       typedef Set::const_iterator     const_iterator;
239
240       /** Singleton access. */
241       static ArchCompatSet & instance()
242       {
243         static ArchCompatSet _instance;
244         return _instance;
245       }
246
247       /** Return the entry related to \a archStr_r.
248        * Creates an entry for nonbuiltin archs.
249       */
250       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
251       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
252       /** \overload */
253       const Arch::CompatEntry & assertDef( IdString archStr_r )
254       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
255
256       const_iterator begin() const
257       { return _compatSet.begin(); }
258
259       const_iterator end() const
260       { return _compatSet.end(); }
261
262       struct DumpOnCompare
263       {
264         int operator()( const CompatEntry & lhs,  const CompatEntry & rhs ) const
265         { return lhs._idBit.value() < rhs._idBit.value(); }
266       };
267
268       std::ostream & dumpOn( std::ostream & str ) const
269       {
270         str << "ArchCompatSet:";
271         std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
272         ov.sort( DumpOnCompare() );
273         for_( it, ov.begin(), ov.end() )
274           {
275             str << endl << ' ' << *it;
276           }
277         return str;
278       }
279
280     private:
281       /** Singleton ctor. */
282       ArchCompatSet()
283       {
284         // _noarch must have _idBit 0.
285         // Other builtins have 1-bit set
286         // and are initialized done on the fly.
287         _compatSet.insert( Arch::CompatEntry( _noarch(), 0 ) );
288         ///////////////////////////////////////////////////////////////////
289         // Define the CompatibleWith relation:
290         //
291         // NOTE: Order of definition is significant! (Arch::compare)
292         //       - define compatible (less) architectures first!
293         //
294         defCompatibleWith( _i386(),             _noarch() );
295         defCompatibleWith( _i486(),             _noarch(),_i386() );
296         defCompatibleWith( _i586(),             _noarch(),_i386(),_i486() );
297         defCompatibleWith( _i686(),             _noarch(),_i386(),_i486(),_i586() );
298         defCompatibleWith( _athlon(),           _noarch(),_i386(),_i486(),_i586(),_i686() );
299         defCompatibleWith( _x86_64(),           _noarch(),_i386(),_i486(),_i586(),_i686(),_athlon() );
300
301         defCompatibleWith( _pentium3(),         _noarch(),_i386(),_i486(),_i586(),_i686() );
302         defCompatibleWith( _pentium4(),         _noarch(),_i386(),_i486(),_i586(),_i686(),_pentium3() );
303
304         defCompatibleWith( _ia64(),             _noarch(),_i386(),_i486(),_i586(),_i686() );
305         //
306         defCompatibleWith( _s390(),             _noarch() );
307         defCompatibleWith( _s390x(),            _noarch(),_s390() );
308         //
309         defCompatibleWith( _ppc(),              _noarch() );
310         defCompatibleWith( _ppc64(),            _noarch(),_ppc() );
311         defCompatibleWith( _ppc64p7(),          _noarch(),_ppc(),_ppc64() );
312         //
313         defCompatibleWith( _ppc64le(),          _noarch() );
314         //
315         defCompatibleWith( _alpha(),            _noarch() );
316         defCompatibleWith( _alphaev5(),         _noarch(),_alpha() );
317         defCompatibleWith( _alphaev56(),        _noarch(),_alpha(),_alphaev5() );
318         defCompatibleWith( _alphapca56(),       _noarch(),_alpha(),_alphaev5(),_alphaev56() );
319         defCompatibleWith( _alphaev6(),         _noarch(),_alpha(),_alphaev5(),_alphaev56(),_alphapca56() );
320         defCompatibleWith( _alphaev67(),        _noarch(),_alpha(),_alphaev5(),_alphaev56(),_alphapca56(),_alphaev6() );
321         //
322         defCompatibleWith( _sparc(),            _noarch() );
323         defCompatibleWith( _sparcv8(),          _noarch(),_sparc() );
324         defCompatibleWith( _sparcv9(),          _noarch(),_sparc(),_sparcv8() );
325         defCompatibleWith( _sparcv9v(),         _noarch(),_sparc(),_sparcv8(),_sparcv9() );
326         //
327         defCompatibleWith( _sparc64(),          _noarch(),_sparc(),_sparcv8(),_sparcv9() );
328         defCompatibleWith( _sparc64v(),         _noarch(),_sparc(),_sparcv8(),_sparcv9(),_sparcv9v(),_sparc64() );
329         //
330         defCompatibleWith( _armv3l(),           _noarch() );
331         defCompatibleWith( _armv4l(),           _noarch(),_armv3l() );
332         defCompatibleWith( _armv4tl(),          _noarch(),_armv3l(),_armv4l() );
333         defCompatibleWith( _armv5l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl() );
334         defCompatibleWith( _armv5tel(),         _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l() );
335         defCompatibleWith( _armv5tejl(),        _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel() );
336         defCompatibleWith( _armv6l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel(),_armv5tejl() );
337         defCompatibleWith( _armv6hl(),          _noarch() );
338         defCompatibleWith( _armv7l(),           _noarch(),_armv3l(),_armv4l(),_armv4tl(),_armv5l(),_armv5tel(),_armv5tejl(),_armv6l() );
339         defCompatibleWith( _armv7hl(),          _noarch(),_armv6hl() );
340         defCompatibleWith( _armv7nhl(),         _noarch(),_armv7hl() );
341         defCompatibleWith( _armv7thl(),         _noarch(),_armv7hl() );
342         defCompatibleWith( _armv7tnhl(),        _noarch(),_armv7hl(),_armv7nhl(),_armv7thl() );
343         defCompatibleWith( _aarch64(),          _noarch() );
344         //
345         defCompatibleWith( _sh3(),              _noarch() );
346         //
347         defCompatibleWith( _sh4(),              _noarch() );
348         defCompatibleWith( _sh4a(),             _noarch(),_sh4() );
349
350         defCompatibleWith(_m68k(),              _noarch());
351         //
352         ///////////////////////////////////////////////////////////////////
353         // dumpOn( USR ) << endl;
354       }
355
356     private:
357       /** Return the next avialable _idBit.
358        * Ctor injects _noarch into the _compatSet, 1 is for
359        * nonbuiltin archs, so we can use <tt>size</tt> for
360        * buitin archs.
361       */
362       CompatBits::IntT nextIdBit() const
363       {
364         if ( CompatBits::size == _compatSet.size() )
365         {
366           // Provide more bits in CompatBits::IntT
367           INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
368           ZYPP_THROW( Exception("Need more bits to encode architectures.") );
369         }
370         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
371         return nextBit;
372       }
373
374       /** Assert each builtin Arch gets an unique _idBit when
375        *  inserted into the _compatSet.
376       */
377       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
378       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
379
380       /** Initialize builtin Archs and set _compatBits.
381       */
382       void defCompatibleWith( IdString targetArch_r,
383                               IdString arch0_r,
384                               IdString arch1_r = IdString(),
385                               IdString arch2_r = IdString(),
386                               IdString arch3_r = IdString(),
387                               IdString arch4_r = IdString(),
388                               IdString arch5_r = IdString(),
389                               IdString arch6_r = IdString(),
390                               IdString arch7_r = IdString(),
391                               IdString arch8_r = IdString(),
392                               IdString arch9_r = IdString() )
393       {
394         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
395         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
396 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
397         _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
398         _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
399 #undef _SETARG
400       }
401
402     private:
403       Set _compatSet;
404     };
405
406     /////////////////////////////////////////////////////////////////
407   } // namespace
408   ///////////////////////////////////////////////////////////////////
409
410   ///////////////////////////////////////////////////////////////////
411   //
412   //    CLASS NAME : Arch
413   //
414   ///////////////////////////////////////////////////////////////////
415
416   const Arch Arch_empty ( IdString::Empty );
417   // remaining Arch_* constants are defined by DEF_BUILTIN above.
418
419   ///////////////////////////////////////////////////////////////////
420   //
421   //    METHOD NAME : Arch::Arch
422   //    METHOD TYPE : Ctor
423   //
424   Arch::Arch()
425   : _entry( &ArchCompatSet::instance().assertDef( _noarch() ) )
426   {}
427
428   Arch::Arch( IdString::IdType id_r )
429   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
430   {}
431
432   Arch::Arch( const IdString & idstr_r )
433   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
434   {}
435
436   Arch::Arch( const std::string & str_r )
437   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
438   {}
439
440   Arch::Arch( const char * cstr_r )
441   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
442   {}
443
444   Arch::Arch( const CompatEntry & rhs )
445   : _entry( &rhs )
446   {}
447
448   ///////////////////////////////////////////////////////////////////
449   //
450   //    METHOD NAME : Arch::idStr
451   //    METHOD TYPE : IdString
452   //
453   IdString Arch::idStr() const
454   { return _entry->_idStr; }
455
456   ///////////////////////////////////////////////////////////////////
457   //
458   //    METHOD NAME : Arch::asString
459   //    METHOD TYPE : const std::string &
460   //
461   const std::string & Arch::asString() const
462   { return _entry->_archStr; }
463
464   ///////////////////////////////////////////////////////////////////
465   //
466   //    METHOD NAME : Arch::isBuiltIn
467   //    METHOD TYPE : bool
468   //
469   bool Arch::isBuiltIn() const
470   { return _entry->isBuiltIn(); }
471
472   ///////////////////////////////////////////////////////////////////
473   //
474   //    METHOD NAME : Arch::compatibleWith
475   //    METHOD TYPE : bool
476   //
477   bool Arch::compatibleWith( const Arch & targetArch_r ) const
478   { return _entry->compatibleWith( *targetArch_r._entry ); }
479
480   ///////////////////////////////////////////////////////////////////
481   //
482   //    METHOD NAME : Arch::baseArch
483   //    METHOD TYPE : Arch
484   //
485   Arch Arch::baseArch( ) const
486   {
487     // check the multilib archs:
488     if (Arch_x86_64.compatibleWith(*this))
489     {
490       return Arch_x86_64;
491     }
492     if (Arch_sparc64v.compatibleWith(*this))
493     {
494       return Arch_sparc64v;
495     }
496     if (Arch_sparc64.compatibleWith(*this))
497     {
498       return Arch_sparc64;
499     }
500     if (Arch_ppc64.compatibleWith(*this))
501     {
502       return Arch_ppc64;
503     }
504     if (Arch_s390x.compatibleWith(*this))
505     {
506       return Arch_s390x;
507     }
508     // Here: no multilib; return arch before noarch
509     CompatSet cset( compatSet( *this ) );
510     if ( cset.size() > 2 )      // systemArchitecture, ..., basearch, noarch
511     {
512       return *(++cset.rbegin());
513     }
514     return *this;
515   }
516
517   ///////////////////////////////////////////////////////////////////
518   //
519   //    METHOD NAME : Arch::compare
520   //    METHOD TYPE : bool
521   //
522   int Arch::compare( const Arch & rhs ) const
523   { return _entry->compare( *rhs._entry ); }
524
525   ///////////////////////////////////////////////////////////////////
526   //
527   //    METHOD NAME : Arch::compatSet
528   //    METHOD TYPE : Arch::CompatSet
529   //
530   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
531   {
532     Arch::CompatSet ret;
533
534     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
535           it != ArchCompatSet::instance().end(); ++it )
536       {
537         if ( it->compatibleWith( *targetArch_r._entry ) )
538           {
539             ret.insert( Arch(*it) );
540           }
541       }
542
543     return ret;
544   }
545
546   /////////////////////////////////////////////////////////////////
547 } // namespace zypp
548 ///////////////////////////////////////////////////////////////////