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