fixup Fix to build with libxml 2.12.x (fixes #505)
[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/Hash.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_##A () { static IdString _str(#A); return _str; } } \
154   const Arch Arch_##A( 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
195   DEF_BUILTIN( armv7tnhl );     /* exists? */
196   DEF_BUILTIN( armv7thl );      /* exists? */
197
198   DEF_BUILTIN( armv7hnl );      /* legacy: */DEF_BUILTIN( armv7nhl );
199   DEF_BUILTIN( armv7hl );
200   DEF_BUILTIN( armv6hl );
201
202   DEF_BUILTIN( armv7l );
203   DEF_BUILTIN( armv6l );
204   DEF_BUILTIN( armv5tejl );
205   DEF_BUILTIN( armv5tel );
206   DEF_BUILTIN( armv5tl );
207   DEF_BUILTIN( armv5l );
208   DEF_BUILTIN( armv4tl );
209   DEF_BUILTIN( armv4l );
210   DEF_BUILTIN( armv3l );
211
212   DEF_BUILTIN( riscv64 );
213
214   DEF_BUILTIN( sh3 );
215
216   DEF_BUILTIN( sh4 );
217   DEF_BUILTIN( sh4a );
218
219   DEF_BUILTIN( m68k );
220
221   DEF_BUILTIN( mips );
222   DEF_BUILTIN( mipsel );
223   DEF_BUILTIN( mips64 );
224   DEF_BUILTIN( mips64el );
225 #undef DEF_BUILTIN
226
227   ///////////////////////////////////////////////////////////////////
228   namespace
229   { /////////////////////////////////////////////////////////////////
230
231     ///////////////////////////////////////////////////////////////////
232     //
233     //  CLASS NAME : CompatSet
234     //
235     /** Maintain architecture compatibility (Singleton by the way it is used).
236      *
237      * Povides \ref Arch::CompatEntry for \ref Arch. Defines the
238      * compatibleWith relation.
239      * \li \c noarch has _idBit 0
240      * \li \c nonbuiltin archs have _idBit 1
241     */
242     struct ArchCompatSet : private base::NonCopyable
243     {
244       typedef Arch::CompatEntry       CompatEntry;
245       typedef CompatEntry::CompatBits CompatBits;
246
247       typedef std::unordered_set<CompatEntry> Set;
248       typedef Set::iterator           iterator;
249       typedef Set::const_iterator     const_iterator;
250
251       /** Singleton access. */
252       static ArchCompatSet & instance()
253       {
254         static ArchCompatSet _instance;
255         return _instance;
256       }
257
258       /** Return the entry related to \a archStr_r.
259        * Creates an entry for nonbuiltin archs.
260       */
261       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
262       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
263       /** \overload */
264       const Arch::CompatEntry & assertDef( IdString archStr_r )
265       { return *_compatSet.insert( Arch::CompatEntry( archStr_r ) ).first; }
266
267       const_iterator begin() const
268       { return _compatSet.begin(); }
269
270       const_iterator end() const
271       { return _compatSet.end(); }
272
273       struct DumpOnCompare
274       {
275         int operator()( const CompatEntry & lhs,  const CompatEntry & rhs ) const
276         { return lhs._idBit.value() < rhs._idBit.value(); }
277       };
278
279       std::ostream & dumpOn( std::ostream & str ) const
280       {
281         str << "ArchCompatSet:";
282         std::list<CompatEntry> ov( _compatSet.begin(), _compatSet.end() );
283         ov.sort( DumpOnCompare() );
284         for_( it, ov.begin(), ov.end() )
285           {
286             str << endl << ' ' << *it;
287           }
288         return str;
289       }
290
291     private:
292       /** Singleton ctor. */
293       ArchCompatSet()
294       {
295         // _noarch must have _idBit 0.
296         // Other builtins have 1-bit set
297         // and are initialized done on the fly.
298         _compatSet.insert( Arch::CompatEntry( a_noarch(), 0 ) );
299         ///////////////////////////////////////////////////////////////////
300         // Define the CompatibleWith relation:
301         //
302         // NOTE: Order of definition is significant! (Arch::compare)
303         //       - define compatible (less) architectures first!
304         //
305         defCompatibleWith( a_i386(),            a_noarch() );
306         defCompatibleWith( a_i486(),            a_noarch(),a_i386() );
307         defCompatibleWith( a_i586(),            a_noarch(),a_i386(),a_i486() );
308         defCompatibleWith( a_i686(),            a_noarch(),a_i386(),a_i486(),a_i586() );
309         defCompatibleWith( a_athlon(),          a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
310         defCompatibleWith( a_x86_64(),          a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_athlon() );
311
312         defCompatibleWith( a_pentium3(),        a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
313         defCompatibleWith( a_pentium4(),        a_noarch(),a_i386(),a_i486(),a_i586(),a_i686(),a_pentium3() );
314
315         defCompatibleWith( a_ia64(),            a_noarch(),a_i386(),a_i486(),a_i586(),a_i686() );
316         //
317         defCompatibleWith( a_s390(),            a_noarch() );
318         defCompatibleWith( a_s390x(),           a_noarch(),a_s390() );
319         //
320         defCompatibleWith( a_ppc(),             a_noarch() );
321         defCompatibleWith( a_ppc64(),           a_noarch(),a_ppc() );
322         defCompatibleWith( a_ppc64p7(),         a_noarch(),a_ppc(),a_ppc64() );
323         //
324         defCompatibleWith( a_ppc64le(),         a_noarch() );
325         //
326         defCompatibleWith( a_alpha(),           a_noarch() );
327         defCompatibleWith( a_alphaev5(),        a_noarch(),a_alpha() );
328         defCompatibleWith( a_alphaev56(),       a_noarch(),a_alpha(),a_alphaev5() );
329         defCompatibleWith( a_alphapca56(),      a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56() );
330         defCompatibleWith( a_alphaev6(),        a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56() );
331         defCompatibleWith( a_alphaev67(),       a_noarch(),a_alpha(),a_alphaev5(),a_alphaev56(),a_alphapca56(),a_alphaev6() );
332         //
333         defCompatibleWith( a_sparc(),           a_noarch() );
334         defCompatibleWith( a_sparcv8(),         a_noarch(),a_sparc() );
335         defCompatibleWith( a_sparcv9(),         a_noarch(),a_sparc(),a_sparcv8() );
336         defCompatibleWith( a_sparcv9v(),        a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() );
337         //
338         defCompatibleWith( a_sparc64(),         a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9() );
339         defCompatibleWith( a_sparc64v(),        a_noarch(),a_sparc(),a_sparcv8(),a_sparcv9(),a_sparcv9v(),a_sparc64() );
340         //
341         defCompatibleWith( a_armv3l(),          a_noarch() );
342         defCompatibleWith( a_armv4l(),          a_noarch(),a_armv3l() );
343         defCompatibleWith( a_armv4tl(),         a_noarch(),a_armv3l(),a_armv4l() );
344         defCompatibleWith( a_armv5l(),          a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl() );
345         defCompatibleWith( a_armv5tl(),         a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l() );
346         defCompatibleWith( a_armv5tel(),        a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl() );
347         defCompatibleWith( a_armv5tejl(),       a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel() );
348         defCompatibleWith( a_armv6l(),          a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl() );
349         defCompatibleWith( a_armv7l(),          a_noarch(),a_armv3l(),a_armv4l(),a_armv4tl(),a_armv5l(),a_armv5tl(),a_armv5tel(),a_armv5tejl(),a_armv6l() );
350
351         defCompatibleWith( a_armv6hl(),         a_noarch() );
352         defCompatibleWith( a_armv7hl(),         a_noarch(),a_armv6hl() );
353         defCompatibleWith( a_armv7hnl(),        a_noarch(),a_armv7hl(),a_armv6hl() );
354         /*legacy: rpm uses v7hnl */
355         defCompatibleWith( a_armv7nhl(),        a_noarch(),a_armv7hnl(),a_armv7hl(),a_armv6hl() );
356
357         /*?*/defCompatibleWith( a_armv7thl(),   a_noarch(),a_armv7hl() );
358         /*?*/defCompatibleWith( a_armv7tnhl(),  a_noarch(),a_armv7hl(),a_armv7nhl(),a_armv7thl() );
359
360         defCompatibleWith( a_aarch64(),         a_noarch() );
361         //
362         defCompatibleWith( a_riscv64(),         a_noarch() );
363         //
364         defCompatibleWith( a_sh3(),             a_noarch() );
365         //
366         defCompatibleWith( a_sh4(),             a_noarch() );
367         defCompatibleWith( a_sh4a(),            a_noarch(),a_sh4() );
368
369         defCompatibleWith( a_m68k(),            a_noarch() );
370
371         defCompatibleWith( a_mips(),            a_noarch() );
372         defCompatibleWith( a_mipsel(),          a_noarch() );
373         defCompatibleWith( a_mips64(),          a_noarch() );
374         defCompatibleWith( a_mips64el(),        a_noarch() );
375         //
376         ///////////////////////////////////////////////////////////////////
377         // dumpOn( USR ) << endl;
378       }
379
380     private:
381       /** Return the next avialable _idBit.
382        * Ctor injects _noarch into the _compatSet, 1 is for
383        * nonbuiltin archs, so we can use <tt>size</tt> for
384        * buitin archs.
385       */
386       CompatBits::IntT nextIdBit() const
387       {
388         if ( CompatBits::size == _compatSet.size() )
389         {
390           // Provide more bits in CompatBits::IntT
391           INT << "Need more than " << CompatBits::size << " bits to encode architectures." << endl;
392           ZYPP_THROW( Exception("Need more bits to encode architectures.") );
393         }
394         CompatBits::IntT nextBit = CompatBits::IntT(1) << (_compatSet.size());
395         return nextBit;
396       }
397
398       /** Assert each builtin Arch gets an unique _idBit when
399        *  inserted into the _compatSet.
400       */
401       const CompatEntry & assertCompatSetEntry( IdString archStr_r )
402       { return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() ) ).first; }
403
404       /** Initialize builtin Archs and set _compatBits.
405       */
406       void defCompatibleWith( IdString targetArch_r,
407                               IdString arch0_r,
408                               IdString arch1_r = IdString(),
409                               IdString arch2_r = IdString(),
410                               IdString arch3_r = IdString(),
411                               IdString arch4_r = IdString(),
412                               IdString arch5_r = IdString(),
413                               IdString arch6_r = IdString(),
414                               IdString arch7_r = IdString(),
415                               IdString arch8_r = IdString(),
416                               IdString arch9_r = IdString() )
417       {
418         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
419         target.addCompatBit( assertCompatSetEntry( arch0_r )._idBit );
420 #define SETARG(N) if ( arch##N##_r.empty() ) return; target.addCompatBit( assertCompatSetEntry( arch##N##_r )._idBit )
421         SETARG(1); SETARG(2); SETARG(3); SETARG(4);
422         SETARG(5); SETARG(6); SETARG(7); SETARG(8); SETARG(9);
423 #undef SETARG
424       }
425
426     private:
427       Set _compatSet;
428     };
429
430     /////////////////////////////////////////////////////////////////
431   } // namespace
432   ///////////////////////////////////////////////////////////////////
433
434   ///////////////////////////////////////////////////////////////////
435   //
436   //    CLASS NAME : Arch
437   //
438   ///////////////////////////////////////////////////////////////////
439
440   const Arch Arch_empty ( IdString::Empty );
441   // remaining Arch_* constants are defined by DEF_BUILTIN above.
442
443   ///////////////////////////////////////////////////////////////////
444   //
445   //    METHOD NAME : Arch::Arch
446   //    METHOD TYPE : Ctor
447   //
448   Arch::Arch()
449   : _entry( &ArchCompatSet::instance().assertDef( a_noarch() ) )
450   {}
451
452   Arch::Arch( IdString::IdType id_r )
453   : _entry( &ArchCompatSet::instance().assertDef( IdString(id_r) ) )
454   {}
455
456   Arch::Arch( const IdString & idstr_r )
457   : _entry( &ArchCompatSet::instance().assertDef( idstr_r ) )
458   {}
459
460   Arch::Arch( const std::string & str_r )
461   : _entry( &ArchCompatSet::instance().assertDef( str_r ) )
462   {}
463
464   Arch::Arch( const char * cstr_r )
465   : _entry( &ArchCompatSet::instance().assertDef( cstr_r ) )
466   {}
467
468   Arch::Arch( const CompatEntry & rhs )
469   : _entry( &rhs )
470   {}
471
472   ///////////////////////////////////////////////////////////////////
473   //
474   //    METHOD NAME : Arch::idStr
475   //    METHOD TYPE : IdString
476   //
477   IdString Arch::idStr() const
478   { return _entry->_idStr; }
479
480   ///////////////////////////////////////////////////////////////////
481   //
482   //    METHOD NAME : Arch::asString
483   //    METHOD TYPE : const std::string &
484   //
485   const std::string & Arch::asString() const
486   { return _entry->_archStr; }
487
488   ///////////////////////////////////////////////////////////////////
489   //
490   //    METHOD NAME : Arch::isBuiltIn
491   //    METHOD TYPE : bool
492   //
493   bool Arch::isBuiltIn() const
494   { return _entry->isBuiltIn(); }
495
496   ///////////////////////////////////////////////////////////////////
497   //
498   //    METHOD NAME : Arch::compatibleWith
499   //    METHOD TYPE : bool
500   //
501   bool Arch::compatibleWith( const Arch & targetArch_r ) const
502   { return _entry->compatibleWith( *targetArch_r._entry ); }
503
504   ///////////////////////////////////////////////////////////////////
505   //
506   //    METHOD NAME : Arch::baseArch
507   //    METHOD TYPE : Arch
508   //
509   Arch Arch::baseArch( ) const
510   {
511     // check the multilib archs:
512     if (Arch_x86_64.compatibleWith(*this))
513     {
514       return Arch_x86_64;
515     }
516     if (Arch_sparc64v.compatibleWith(*this))
517     {
518       return Arch_sparc64v;
519     }
520     if (Arch_sparc64.compatibleWith(*this))
521     {
522       return Arch_sparc64;
523     }
524     if (Arch_ppc64.compatibleWith(*this))
525     {
526       return Arch_ppc64;
527     }
528     if (Arch_s390x.compatibleWith(*this))
529     {
530       return Arch_s390x;
531     }
532     // Here: no multilib; return arch before noarch
533     CompatSet cset( compatSet( *this ) );
534     if ( cset.size() > 2 )      // systemArchitecture, ..., basearch, noarch
535     {
536       return *(++cset.rbegin());
537     }
538     return *this;
539   }
540
541   ///////////////////////////////////////////////////////////////////
542   //
543   //    METHOD NAME : Arch::compare
544   //    METHOD TYPE : bool
545   //
546   int Arch::compare( const Arch & rhs ) const
547   { return _entry->compare( *rhs._entry ); }
548
549   ///////////////////////////////////////////////////////////////////
550   //
551   //    METHOD NAME : Arch::compatSet
552   //    METHOD TYPE : Arch::CompatSet
553   //
554   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
555   {
556     Arch::CompatSet ret;
557
558     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
559           it != ArchCompatSet::instance().end(); ++it )
560       {
561         if ( it->compatibleWith( *targetArch_r._entry ) )
562           {
563             ret.insert( Arch(*it) );
564           }
565       }
566
567     return ret;
568   }
569
570   /////////////////////////////////////////////////////////////////
571 } // namespace zypp
572 ///////////////////////////////////////////////////////////////////