Add missing entries for const Arch Arch_armv7(n)hl .
[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 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   ///////////////////////////////////////////////////////////////////
141   namespace
142   { /////////////////////////////////////////////////////////////////
143
144     // Builtin architecture STRING VALUES to be
145     // used in defCompatibleWith below!
146     //
147     // const IdString  _foo( "foo" );
148     //
149     // NOTE: Builtin CLASS Arch CONSTANTS are defined below.
150     //       You have to change them accordingly.
151     //
152     // NOTE: Thake care CompatBits::IntT is able to provide one
153     //       bit for each architecture.
154     //
155 #define DEF_BUILTIN(A) const IdString  _##A( #A );
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
174     DEF_BUILTIN( ia64 );
175
176     DEF_BUILTIN( alphaev67 );
177     DEF_BUILTIN( alphaev6 );
178     DEF_BUILTIN( alphapca56 );
179     DEF_BUILTIN( alphaev56 );
180     DEF_BUILTIN( alphaev5 );
181     DEF_BUILTIN( alpha );
182
183     DEF_BUILTIN( sparc64v );
184     DEF_BUILTIN( sparcv9v );
185     DEF_BUILTIN( sparc64 );
186     DEF_BUILTIN( sparcv9 );
187     DEF_BUILTIN( sparcv8 );
188     DEF_BUILTIN( sparc );
189
190     DEF_BUILTIN( armv7nhl );
191     DEF_BUILTIN( armv7hl );
192     DEF_BUILTIN( armv7l );
193     DEF_BUILTIN( armv6l );
194     DEF_BUILTIN( armv5tejl );
195     DEF_BUILTIN( armv5tel );
196     DEF_BUILTIN( armv5l );
197     DEF_BUILTIN( armv4tl );
198     DEF_BUILTIN( armv4l );
199     DEF_BUILTIN( armv3l );
200
201     DEF_BUILTIN( sh3 );
202
203     DEF_BUILTIN( sh4 );
204     DEF_BUILTIN( sh4a );
205 #undef DEF_BUILTIN
206
207     ///////////////////////////////////////////////////////////////////
208     //
209     //  CLASS NAME : CompatSet
210     //
211     /** Maintain architecture compatibility (Singleton by the way it is used).
212      *
213      * Povides \ref Arch::CompatEntry for \ref Arch. Defines the
214      * compatibleWith relation.
215      * \li \c noarch has _idBit 0
216      * \li \c nonbuiltin archs have _idBit 1
217     */
218     struct ArchCompatSet : private base::NonCopyable
219     {
220       typedef Arch::CompatEntry       CompatEntry;
221       typedef CompatEntry::CompatBits CompatBits;
222
223       typedef std::tr1::unordered_set<CompatEntry> Set;
224       typedef Set::iterator           iterator;
225       typedef Set::const_iterator     const_iterator;
226
227       /** Singleton access. */
228       static ArchCompatSet & instance()
229       {
230         static ArchCompatSet _instance;
231         return _instance;
232       }
233
234       /** Return the entry related to \a archStr_r.
235        * Creates an entry for nonbuiltin archs.
236       */
237       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
238       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
239       /** \overload */
240       const Arch::CompatEntry & assertDef( IdString archStr_r )
241       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
242
243       const_iterator begin() const
244       { return _compatSet.begin(); }
245
246       const_iterator end() const
247       { return _compatSet.end(); }
248
249       struct DumpOnCompare
250       {
251         int operator()( const CompatEntry & lhs,  const CompatEntry & rhs ) const
252         { return lhs._idBit.value() < rhs._idBit.value(); }
253       };
254
255       std::ostream & dumpOn( std::ostream & str ) const
256       {
257         str << "ArchCompatSet:";
258         std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
259         ov.sort( DumpOnCompare() );
260         for_( it, ov.begin(), ov.end() )
261           {
262             str << endl << ' ' << *it;
263           }
264         return str;
265       }
266
267     private:
268       /** Singleton ctor. */
269       ArchCompatSet()
270       {
271         // _noarch must have _idBit 0.
272         // Other builtins have 1-bit set
273         // and are initialized done on the fly.
274         _compatSet.insert( Arch::CompatEntry( _noarch, 0 ) );
275         ///////////////////////////////////////////////////////////////////
276         // Define the CompatibleWith relation:
277         //
278         // NOTE: Order of definition is significant! (Arch::compare)
279         //       - define compatible (less) architectures first!
280         //
281         defCompatibleWith( _i386,       _noarch );
282         defCompatibleWith( _i486,       _noarch,_i386 );
283         defCompatibleWith( _i586,       _noarch,_i386,_i486 );
284         defCompatibleWith( _i686,       _noarch,_i386,_i486,_i586 );
285         defCompatibleWith( _athlon,     _noarch,_i386,_i486,_i586,_i686 );
286         defCompatibleWith( _x86_64,     _noarch,_i386,_i486,_i586,_i686,_athlon );
287
288         defCompatibleWith( _pentium3,   _noarch,_i386,_i486,_i586,_i686 );
289         defCompatibleWith( _pentium4,   _noarch,_i386,_i486,_i586,_i686,_pentium3 );
290
291         defCompatibleWith( _ia64,       _noarch,_i386,_i486,_i586,_i686 );
292         //
293         defCompatibleWith( _s390,       _noarch );
294         defCompatibleWith( _s390x,      _noarch,_s390 );
295         //
296         defCompatibleWith( _ppc,        _noarch );
297         defCompatibleWith( _ppc64,      _noarch,_ppc );
298         //
299         defCompatibleWith( _alpha,      _noarch );
300         defCompatibleWith( _alphaev5,   _noarch,_alpha );
301         defCompatibleWith( _alphaev56,  _noarch,_alpha,_alphaev5 );
302         defCompatibleWith( _alphapca56, _noarch,_alpha,_alphaev5,_alphaev56 );
303         defCompatibleWith( _alphaev6,   _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56 );
304         defCompatibleWith( _alphaev67,  _noarch,_alpha,_alphaev5,_alphaev56,_alphapca56,_alphaev6 );
305         //
306         defCompatibleWith( _sparc,      _noarch );
307         defCompatibleWith( _sparcv8,    _noarch,_sparc );
308         defCompatibleWith( _sparcv9,    _noarch,_sparc,_sparcv8 );
309         defCompatibleWith( _sparcv9v,   _noarch,_sparc,_sparcv8,_sparcv9 );
310         //
311         defCompatibleWith( _sparc64,    _noarch,_sparc,_sparcv8,_sparcv9 );
312         defCompatibleWith( _sparc64v,   _noarch,_sparc,_sparcv8,_sparcv9,_sparcv9v,_sparc64 );
313         //
314         defCompatibleWith( _armv3l,     _noarch );
315         defCompatibleWith( _armv4l,     _noarch,_armv3l );
316         defCompatibleWith( _armv4tl,    _noarch,_armv3l,_armv4l );
317         defCompatibleWith( _armv5l,     _noarch,_armv3l,_armv4l,_armv4tl );
318         defCompatibleWith( _armv5tel,   _noarch,_armv3l,_armv4l,_armv4tl,_armv5l );
319         defCompatibleWith( _armv5tejl,  _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel );
320         defCompatibleWith( _armv6l,     _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl );
321         defCompatibleWith( _armv7l,     _noarch,_armv3l,_armv4l,_armv4tl,_armv5l,_armv5tel,_armv5tejl,_armv6l );
322         defCompatibleWith( _armv7hl,    _noarch );
323         defCompatibleWith( _armv7nhl,   _noarch, _armv7hl );
324         //
325         defCompatibleWith( _sh3,        _noarch );
326         //
327         defCompatibleWith( _sh4,        _noarch );
328         defCompatibleWith( _sh4a,       _noarch,_sh4 );
329         //
330         ///////////////////////////////////////////////////////////////////
331         // dumpOn( USR ) << endl;
332       }
333
334     private:
335       /** Return the next avialable _idBit.
336        * Ctor injects _noarch into the _compatSet, 1 is for
337        * nonbuiltin archs, so we can use <tt>size</tt> for
338        * buitin archs.
339       */
340       CompatBits::IntT nextIdBit() const
341       {
342         if ( CompatBits::size == _compatSet.size() )
343         {
344           // Provide more bits in CompatBits::IntT
345           INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
346           ZYPP_THROW( Exception("Need more bits to encode architectures.") );
347         }
348         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
349         return nextBit;
350       }
351
352       /** Assert each builtin Arch gets an unique _idBit when
353        *  inserted into the _compatSet.
354       */
355       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
356       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
357
358       /** Initialize builtin Archs and set _compatBits.
359       */
360       void defCompatibleWith( IdString targetArch_r,
361                               IdString arch0_r,
362                               IdString arch1_r = IdString(),
363                               IdString arch2_r = IdString(),
364                               IdString arch3_r = IdString(),
365                               IdString arch4_r = IdString(),
366                               IdString arch5_r = IdString(),
367                               IdString arch6_r = IdString(),
368                               IdString arch7_r = IdString(),
369                               IdString arch8_r = IdString(),
370                               IdString arch9_r = IdString() )
371       {
372         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
373         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
374 #define _SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
375         _SETARG(1); _SETARG(2); _SETARG(3); _SETARG(4);
376         _SETARG(5); _SETARG(6); _SETARG(7); _SETARG(8); _SETARG(9);
377 #undef _SETARG
378       }
379
380     private:
381       Set _compatSet;
382     };
383
384     /////////////////////////////////////////////////////////////////
385   } // namespace
386   ///////////////////////////////////////////////////////////////////
387
388   ///////////////////////////////////////////////////////////////////
389   //
390   //    CLASS NAME : Arch
391   //
392   ///////////////////////////////////////////////////////////////////
393
394   const Arch Arch_empty ( IdString::Empty );
395   const Arch Arch_noarch( _noarch );
396
397   const Arch Arch_i386( _i386 );
398   const Arch Arch_i486( _i486 );
399   const Arch Arch_i586( _i586 );
400   const Arch Arch_i686( _i686 );
401   const Arch Arch_athlon( _athlon );
402   const Arch Arch_x86_64( _x86_64 );
403
404   const Arch Arch_pentium3( _pentium3 );
405   const Arch Arch_pentium4( _pentium4 );
406
407   const Arch Arch_s390( _s390 );
408   const Arch Arch_s390x( _s390x );
409
410   const Arch Arch_ppc( _ppc );
411   const Arch Arch_ppc64( _ppc64 );
412
413   const Arch Arch_ia64( _ia64 );
414
415   const Arch Arch_alphaev67( _alphaev67 );
416   const Arch Arch_alphaev6( _alphaev6 );
417   const Arch Arch_alphapca56( _alphapca56 );
418   const Arch Arch_alphaev56( _alphaev56 );
419   const Arch Arch_alphaev5( _alphaev5 );
420   const Arch Arch_alpha( _alpha );
421
422   const Arch Arch_sparc64v( _sparc64v );
423   const Arch Arch_sparc64( _sparc64 );
424   const Arch Arch_sparcv9v( _sparcv9v );
425   const Arch Arch_sparcv9( _sparcv9 );
426   const Arch Arch_sparcv8( _sparcv8 );
427   const Arch Arch_sparc( _sparc );
428
429   const Arch Arch_armv7nhl ( _armv7nhl );
430   const Arch Arch_armv7hl ( _armv7hl );
431   const Arch Arch_armv7l( _armv7l );
432   const Arch Arch_armv6l( _armv6l );
433   const Arch Arch_armv5tejl( _armv5tejl );
434   const Arch Arch_armv5tel( _armv5tel );
435   const Arch Arch_armv5l( _armv5l );
436   const Arch Arch_armv4tl( _armv4tl );
437   const Arch Arch_armv4l( _armv4l );
438   const Arch Arch_armv3l( _armv3l );
439
440   const Arch Arch_sh3( _sh3 );
441
442   const Arch Arch_sh4( _sh4 );
443   const Arch Arch_sh4a( _sh4a );
444
445   ///////////////////////////////////////////////////////////////////
446   //
447   //    METHOD NAME : Arch::Arch
448   //    METHOD TYPE : Ctor
449   //
450   Arch::Arch()
451   : _entry( &ArchCompatSet::instance().assertDef( _noarch ) )
452   {}
453
454   Arch::Arch( IdString::IdType id_r )
455   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
456   {}
457
458   Arch::Arch( const IdString & idstr_r )
459   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
460   {}
461
462   Arch::Arch( const std::string & str_r )
463   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
464   {}
465
466   Arch::Arch( const char * cstr_r )
467   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
468   {}
469
470   Arch::Arch( const CompatEntry & rhs )
471   : _entry( &rhs )
472   {}
473
474   ///////////////////////////////////////////////////////////////////
475   //
476   //    METHOD NAME : Arch::idStr
477   //    METHOD TYPE : IdString
478   //
479   IdString Arch::idStr() const
480   { return _entry->_idStr; }
481
482   ///////////////////////////////////////////////////////////////////
483   //
484   //    METHOD NAME : Arch::asString
485   //    METHOD TYPE : const std::string &
486   //
487   const std::string & Arch::asString() const
488   { return _entry->_archStr; }
489
490   ///////////////////////////////////////////////////////////////////
491   //
492   //    METHOD NAME : Arch::isBuiltIn
493   //    METHOD TYPE : bool
494   //
495   bool Arch::isBuiltIn() const
496   { return _entry->isBuiltIn(); }
497
498   ///////////////////////////////////////////////////////////////////
499   //
500   //    METHOD NAME : Arch::compatibleWith
501   //    METHOD TYPE : bool
502   //
503   bool Arch::compatibleWith( const Arch & targetArch_r ) const
504   { return _entry->compatibleWith( *targetArch_r._entry ); }
505
506   ///////////////////////////////////////////////////////////////////
507   //
508   //    METHOD NAME : Arch::baseArch
509   //    METHOD TYPE : Arch
510   //
511   Arch Arch::baseArch( ) const
512   {
513     // check the multilib archs:
514     if (Arch_x86_64.compatibleWith(*this))
515     {
516       return Arch_x86_64;
517     }
518     if (Arch_sparc64v.compatibleWith(*this))
519     {
520       return Arch_sparc64v;
521     }
522     if (Arch_sparc64.compatibleWith(*this))
523     {
524       return Arch_sparc64;
525     }
526     if (Arch_ppc64.compatibleWith(*this))
527     {
528       return Arch_ppc64;
529     }
530     if (Arch_s390x.compatibleWith(*this))
531     {
532       return Arch_s390x;
533     }
534     // Here: no multilib; return arch before noarch
535     CompatSet cset( compatSet( *this ) );
536     if ( cset.size() > 2 )      // systemArchitecture, ..., basearch, noarch
537     {
538       return *(++cset.rbegin());
539     }
540     return *this;
541   }
542
543   ///////////////////////////////////////////////////////////////////
544   //
545   //    METHOD NAME : Arch::compare
546   //    METHOD TYPE : bool
547   //
548   int Arch::compare( const Arch & rhs ) const
549   { return _entry->compare( *rhs._entry ); }
550
551   ///////////////////////////////////////////////////////////////////
552   //
553   //    METHOD NAME : Arch::compatSet
554   //    METHOD TYPE : Arch::CompatSet
555   //
556   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
557   {
558     Arch::CompatSet ret;
559
560     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
561           it != ArchCompatSet::instance().end(); ++it )
562       {
563         if ( it->compatibleWith( *targetArch_r._entry ) )
564           {
565             ret.insert( Arch(*it) );
566           }
567       }
568
569     return ret;
570   }
571
572   /////////////////////////////////////////////////////////////////
573 } // namespace zypp
574 ///////////////////////////////////////////////////////////////////