- Create the cache directly from the schema (installed) file.
[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 <set>
14
15 #include "zypp/base/Logger.h"
16 #include "zypp/base/NonCopyable.h"
17 #include "zypp/Arch.h"
18 #include "zypp/Bit.h"
19
20 using namespace std;
21
22 ///////////////////////////////////////////////////////////////////
23 namespace zypp
24 { /////////////////////////////////////////////////////////////////
25
26   ///////////////////////////////////////////////////////////////////
27   //
28   //    CLASS NAME : Arch::CompatEntry
29   //
30   /** Holds an architecture ID and it's compatible relation.
31    * An architecture is compatibleWith, if it's _idBit is set in
32    * _compatBits. noarch has ID 0, non builtin archs id 1 and
33    * have to be treated specialy.
34   */
35   struct Arch::CompatEntry
36   {
37     /** Bitfield for architecture IDs and compatBits relation.
38      * \note Need one bit for each builtin Arch.
39     */
40     typedef bit::BitField<uint16_t> CompatBits;
41
42     CompatEntry( const std::string & archStr_r,
43                  CompatBits::IntT idBit_r = CompatBits::IntT(1) )
44     : _archStr( archStr_r )
45     , _idBit( idBit_r )
46     , _compatBits( idBit_r )
47     , _compatScore( idBit_r ? 1 : 0 ) // number of compatible archs
48     {}
49
50     void addCompatBit( const CompatBits & idBit_r ) const
51     {
52       if ( idBit_r && ! (_compatBits & idBit_r) )
53         {
54           _compatBits |= idBit_r;
55           ++_compatScore;
56         }
57     }
58
59     /** Return whether \c this is compatible with \a targetEntry_r.*/
60     bool compatibleWith( const CompatEntry & targetEntry_r ) const
61     {
62       switch ( _idBit.value() )
63         {
64         case 0:
65           // this is noarch and always comatible
66           return true;
67           break;
68         case 1:
69           // this is a non builtin: self compatible only
70           return _archStr == targetEntry_r._archStr;
71           break;
72         }
73       // This is a builtin: comatible if mentioned in targetEntry_r
74       return targetEntry_r._compatBits & _idBit;
75     }
76
77     /** compare by score, then archStr. */
78     int compare( const CompatEntry & rhs ) const
79     {
80       if ( _compatScore != rhs._compatScore )
81         return( _compatScore < rhs._compatScore ? -1 : 1 );
82       return _archStr.compare( rhs._archStr );
83     }
84
85     std::string         _archStr;
86     CompatBits          _idBit;
87     mutable CompatBits  _compatBits;
88     mutable unsigned    _compatScore;
89   };
90   ///////////////////////////////////////////////////////////////////
91
92   /** \relates Arch::CompatEntry Stream output */
93   inline std::ostream & operator<<( std::ostream & str, const Arch::CompatEntry & obj )
94   {
95     return str << obj._archStr << '\t' << obj._idBit << ' '
96                << obj._compatBits << ' ' << obj._compatScore;
97   }
98
99   /** \relates Arch::CompatEntry ComaptSet ordering.
100    * \note This is purely based on _archStr, as required by class ComaptSet.
101   */
102   inline bool operator<( const Arch::CompatEntry & lhs, const Arch::CompatEntry & rhs )
103   { return lhs._archStr < rhs._archStr; }
104
105   ///////////////////////////////////////////////////////////////////
106   namespace
107   { /////////////////////////////////////////////////////////////////
108
109     // builtin architecture STRING VALUES
110 #define DEF_BUILTIN(A) const std::string  _##A( #A )
111
112     DEF_BUILTIN( noarch );
113
114     DEF_BUILTIN( i386 );
115     DEF_BUILTIN( i486 );
116     DEF_BUILTIN( i586 );
117     DEF_BUILTIN( i686 );
118     DEF_BUILTIN( athlon );
119     DEF_BUILTIN( x86_64 );
120
121     DEF_BUILTIN( ia64 );
122
123     DEF_BUILTIN( s390 );
124     DEF_BUILTIN( s390x );
125
126     DEF_BUILTIN( ppc );
127     DEF_BUILTIN( ppc64 );
128
129 #undef DEF_BUILTIN
130
131     ///////////////////////////////////////////////////////////////////
132     //
133     //  CLASS NAME : CompatSet
134     //
135     /** Maintain architecture compatibility (Singleton by the way it is used).
136      *
137      * Povides \ref Arch::CompatEntry for \ref Arch. Defines the
138      * compatibleWith relation.
139      * \li \c noarch has _idBit 0
140      * \li \c nonbuiltin archs have _idBit 1
141     */
142     struct ArchCompatSet : private base::NonCopyable
143     {
144       typedef Arch::CompatEntry       CompatEntry;
145       typedef CompatEntry::CompatBits CompatBits;
146
147       typedef std::set<CompatEntry>   Set;
148       typedef Set::iterator           iterator;
149       typedef Set::const_iterator     const_iterator;
150
151       /** Singleton access. */
152       static ArchCompatSet & instance()
153       {
154         static ArchCompatSet _instance;
155         return _instance;
156       }
157
158       /** Return the entry related to \a archStr_r.
159        * Creates an entry for nonbuiltin archs.
160       */
161       const Arch::CompatEntry & assertDef( const std::string & archStr_r )
162       {
163         return *_compatSet.insert( Arch::CompatEntry( archStr_r )
164                                  ).first;
165       }
166
167       const_iterator begin() const
168       { return _compatSet.begin(); }
169
170       const_iterator end() const
171       { return _compatSet.end(); }
172
173       std::ostream & dumpOn( std::ostream & str ) const
174       {
175         str << "ArchCompatSet:";
176         for ( const_iterator it = _compatSet.begin(); it != _compatSet.end(); ++it )
177           {
178             str << endl << ' ' << *it;
179           }
180         return str;
181       }
182
183     private:
184       /** Singleton ctor. */
185       ArchCompatSet()
186       {
187         // _noarch must have _idBit 0.
188         // Other builtins have 1-bit set
189         // and are intiialized done on the fly.
190         _compatSet.insert( Arch::CompatEntry( _noarch, 0 ) );
191         ///////////////////////////////////////////////////////////////////
192         // Define the CompatibleWith relation:
193         //
194         defCompatibleWith( _noarch,     _i386 );
195
196         defCompatibleWith( _noarch,     _i486 );
197         defCompatibleWith( _i386,       _i486 );
198
199         defCompatibleWith( _noarch,     _i586 );
200         defCompatibleWith( _i386,       _i586 );
201         defCompatibleWith( _i486,       _i586 );
202
203         defCompatibleWith( _noarch,     _i686 );
204         defCompatibleWith( _i386,       _i686 );
205         defCompatibleWith( _i486,       _i686 );
206         defCompatibleWith( _i586,       _i686 );
207
208         defCompatibleWith( _noarch,     _athlon );
209         defCompatibleWith( _i386,       _athlon );
210         defCompatibleWith( _i486,       _athlon );
211         defCompatibleWith( _i586,       _athlon );
212         defCompatibleWith( _i686,       _athlon );
213
214         defCompatibleWith( _noarch,     _x86_64 );
215         defCompatibleWith( _i386,       _x86_64 );
216         defCompatibleWith( _i486,       _x86_64 );
217         defCompatibleWith( _i586,       _x86_64 );
218         defCompatibleWith( _i686,       _x86_64 );
219         defCompatibleWith( _athlon,     _x86_64 );
220
221         /////
222         defCompatibleWith( _noarch,     _ia64 );
223         defCompatibleWith( _i386,       _ia64 );
224         defCompatibleWith( _i486,       _ia64 );
225         defCompatibleWith( _i586,       _ia64 );
226         defCompatibleWith( _i686,       _ia64 );
227
228         /////
229         defCompatibleWith( _noarch,     _s390 );
230
231         defCompatibleWith( _noarch,     _s390x );
232         defCompatibleWith( _s390,       _s390x );
233
234         /////
235         defCompatibleWith( _noarch,     _ppc );
236
237         defCompatibleWith( _noarch,     _ppc64 );
238         defCompatibleWith( _ppc,        _ppc64 );
239         //
240         ///////////////////////////////////////////////////////////////////
241       }
242
243     private:
244       /** Return the next avialable _idBit.
245        * Ctor injects _noarch into the _compatSet, 1 is for
246        * nonbuiltin archs, so we can use <tt>size</tt> for
247        * buitin archs.
248       */
249       CompatBits::IntT nextIdBit() const
250       {
251         CompatBits::IntT nextBit = 1 << (_compatSet.size());
252         assert( nextBit ); // need more bits in CompatBits::IntT
253         return nextBit;
254       }
255
256       /** Assert each builtin Arch gets an unique _idBit when
257        *  inserted into the _compatSet.
258       */
259       const CompatEntry & assertCompatSetEntry( const std::string & archStr_r )
260       {
261         return *_compatSet.insert( Arch::CompatEntry( archStr_r, nextIdBit() )
262                                  ).first;
263       }
264
265       /** Initialize builtin Archs and set _compatBits.
266       */
267       void defCompatibleWith( const std::string & arch_r, const std::string & targetArch_r )
268       {
269         const CompatEntry & arch  ( assertCompatSetEntry( arch_r ) );
270         const CompatEntry & target( assertCompatSetEntry( targetArch_r ) );
271         target.addCompatBit( arch._idBit );
272       }
273
274     private:
275       Set _compatSet;
276     };
277
278     /////////////////////////////////////////////////////////////////
279   } // namespace
280   ///////////////////////////////////////////////////////////////////
281
282   ///////////////////////////////////////////////////////////////////
283
284   static const string canonical_arch (const string & arch);
285
286   //---------------------------------------------------------------------------
287   // architecture stuff
288
289   static const string
290   canonical_arch (const string & arch)
291   {
292     typedef struct { char *from; char *to; } canonical;
293     // convert machine string to known_arch
294     static canonical canonical_archs[] = {
295       { "noarch",  "noarch" },
296       { "unknown", "unknown" },
297       { "any",     "any" },
298       { "all",     "any" },
299       { "i386",    "i386" },
300       { "ix86",    "i386" }, /* OpenPKG uses this */
301       { "i486",    "i486" },
302       { "i586",    "i586" },
303       { "i686",    "i686" },
304       { "x86_64",  "x86_64" },
305       { "ia32e",   "ia32e" },
306       { "athlon",  "athlon" },
307       { "ppc",     "ppc" },
308       { "ppc64",   "ppc64" },
309       { "s390",    "s390" },
310       { "s390x",   "s390x" },
311       { "ia64",    "ia64" },
312       { "sparc",   "sparc" },
313       { "sun4c",   "sparc" },
314       { "sun4d",   "sparc" },
315       { "sun4m",   "sparc" },
316       { "sparc64", "sparc64" },
317       { "sun4u",   "sparc64" },
318       { "sparcv9", "sparc64" },
319       { 0, 0 }
320     };
321
322     for (canonical *ptr = canonical_archs; ptr->from; ptr++) {
323       if (arch == ptr->from) {
324         return ptr->to;
325       }
326     }
327
328     return "canonical";
329   }
330
331   //---------------------------------------------------------------------------
332
333   ///////////////////////////////////////////////////////////////////
334   //
335   //    CLASS NAME : Arch
336   //
337   ///////////////////////////////////////////////////////////////////
338
339   const Arch Arch_noarch( _noarch );
340
341   const Arch Arch_x86_64( _x86_64 );
342   const Arch Arch_athlon( _athlon );
343   const Arch Arch_i686  ( _i686 );
344   const Arch Arch_i586  ( _i586 );
345   const Arch Arch_i486  ( _i486 );
346   const Arch Arch_i386  ( _i386 );
347
348   const Arch Arch_s390x ( _s390x );
349   const Arch Arch_s390  ( _s390 );
350
351   const Arch Arch_ppc64 ( _ppc64 );
352   const Arch Arch_ppc   ( _ppc );
353
354   const Arch Arch_ia64  ( _ia64 );
355
356   ///////////////////////////////////////////////////////////////////
357   //
358   //    METHOD NAME : Arch::Arch
359   //    METHOD TYPE : Ctor
360   //
361   Arch::Arch()
362   : _entry( &ArchCompatSet::instance().assertDef( _noarch ) )
363   { assert( _entry ); }
364
365   ///////////////////////////////////////////////////////////////////
366   //
367   //    METHOD NAME : Arch::Arch
368   //    METHOD TYPE : Ctor
369   //
370   Arch::Arch( const std::string & rhs )
371   : _entry( &ArchCompatSet::instance().assertDef( rhs ) )
372   { assert( _entry ); }
373
374   ///////////////////////////////////////////////////////////////////
375   //
376   //    METHOD NAME : Arch::Arch
377   //    METHOD TYPE : Ctor
378   //
379   Arch::Arch( const CompatEntry & rhs )
380   : _entry( &rhs )
381   { assert( _entry ); }
382
383   ///////////////////////////////////////////////////////////////////
384   //
385   //    METHOD NAME : Arch::asString
386   //    METHOD TYPE : const std::string &
387   //
388   const std::string & Arch::asString() const
389   { return _entry->_archStr; }
390
391   ///////////////////////////////////////////////////////////////////
392   //
393   //    METHOD NAME : Arch::compatibleWith
394   //    METHOD TYPE : bool
395   //
396   bool Arch::compatibleWith( const Arch & targetArch_r ) const
397   { return _entry->compatibleWith( *targetArch_r._entry ); }
398
399   ///////////////////////////////////////////////////////////////////
400   //
401   //    METHOD NAME : Arch::compare
402   //    METHOD TYPE : bool
403   //
404   int Arch::compare( const Arch & rhs ) const
405   { return _entry->compare( *rhs._entry ); }
406
407   ///////////////////////////////////////////////////////////////////
408   //
409   //    METHOD NAME : Arch::compatSet
410   //    METHOD TYPE : Arch::CompatSet
411   //
412   Arch::CompatSet Arch::compatSet( const Arch & targetArch_r )
413   {
414     Arch::CompatSet ret;
415
416     for ( ArchCompatSet::const_iterator it = ArchCompatSet::instance().begin();
417           it != ArchCompatSet::instance().end(); ++it )
418       {
419         if ( it->compatibleWith( *targetArch_r._entry ) )
420           {
421             ret.insert( Arch(*it) );
422           }
423       }
424
425     return ret;
426   }
427
428
429   /////////////////////////////////////////////////////////////////
430 } // namespace zypp
431 ///////////////////////////////////////////////////////////////////