LTP GCOV extension - code coverage report
Current view: directory - ept/core/apt - record.h
Test: lcov.info
Date: 2008-08-14 Instrumented lines: 96
Code covered: 86.5 % Executed lines: 83

       1                 : // -*- C++ -*-
       2                 : 
       3                 : #include <ept/core/apt/recordparser.h>
       4                 : 
       5                 : #ifndef EPT_APT_RECORD_H
       6                 : #define EPT_APT_RECORD_H
       7                 : 
       8                 : namespace ept {
       9                 : namespace core {
      10                 : namespace record {
      11                 : 
      12                 : struct Source;
      13                 : 
      14                 : struct InternalList {
      15                 :     Source *m_source;
      16                 :     size_t m_idx;
      17                 : 
      18                 :     Internal head();
      19                 :     const Internal head() const;
      20                 :     bool empty() const;
      21                 : 
      22             870 :     InternalList tail() const {
      23             870 :         InternalList t = *this;
      24             870 :         ++ t.m_idx;
      25                 :         return t;
      26                 :     }
      27                 : 
      28               2 :     InternalList( Source &s )
      29               2 :         : m_source( &s ), m_idx( 0 )
      30               2 :     {}
      31                 : };
      32                 : 
      33                 : struct Setup {
      34                 :     typedef ept::Token Token;
      35                 :     typedef record::Internal Internal;
      36                 :     typedef record::PropertyId PropertyId;
      37                 :     typedef record::InternalList InternalList;
      38                 : };
      39                 : 
      40                 : template<> struct PropertyType< InstalledSize > { typedef int T; };
      41                 : template<> struct PropertyType< PackageSize > { typedef int T; };
      42                 : 
      43                 : struct Parser: RecordParser
      44            1310 : {
      45                 :     bool parseBool(bool& def, const std::string& str) const
      46                 :     {
      47                 :         // Believe it or not, this is what apt does to interpret bool fields
      48                 :         if (str == "no" || str == "false" || str == "without" ||
      49                 :             str == "off" || str == "disable")
      50                 :             return false;
      51                 : 
      52                 :         if (str == "yes" || str == "true" || str == "with" ||
      53                 :             str == "on" || str == "enable")
      54                 :             return true;
      55                 : 
      56                 :         return def;
      57                 :     }
      58                 : 
      59                 : public:
      60                 :     Parser() : RecordParser() {}
      61            1310 :     Parser(const std::string& str) : RecordParser(str) {}
      62                 : 
      63                 :     template< PropertyId p >
      64                 :     typename PropertyType< p >::T parse( typename PropertyType< p >::T def,
      65                 :                                          std::string data );
      66                 : 
      67                 :     template< typename T >
      68                 :     struct Default {
      69                 :         static T def;
      70                 :     };
      71                 : 
      72                 :     template< typename T > T parse( const T &def,
      73                 :                                     const std::string &field ) const;
      74                 : 
      75                 :     template< PropertyId p >
      76                 :     typename PropertyType< p >::T get(
      77                 :         const typename PropertyType< p >::T &def
      78            1308 :         = Default< typename PropertyType< p >::T >::def ) const
      79                 :     {
      80                 :         return parse< typename PropertyType< p >::T >( def,
      81            1308 :                                                        lookup( fields[ p ] ) );
      82                 :     }
      83                 : 
      84                 : };
      85                 : 
      86              25 : template< typename T > T Parser::Default< T >::def = T();
      87                 : 
      88                 : template<> inline std::string Parser::get< ShortDescription >(
      89               2 :     const std::string& def ) const
      90                 : {
      91               2 :     std::string str = lookup( fields[ Description ] );
      92               4 :     if (str == std::string())
      93               1 :         return def;
      94               1 :     size_t pos = str.find("\n");
      95               1 :     if (pos == std::string::npos)
      96               0 :         return str;
      97                 :     else
      98               1 :         return str.substr(0, pos);
      99                 : }
     100                 : 
     101                 : template<> inline std::string Parser::get< LongDescription >(
     102                 :     const std::string& def ) const
     103                 : {
     104                 :     std::string str = lookup( fields[ Description ] );
     105                 :     if (str == std::string())
     106                 :         return def;
     107                 :     size_t pos = str.find("\n");
     108                 :     if (pos == std::string::npos)
     109                 :         return str;
     110                 :     else
     111                 :     {
     112                 :         // Trim trailing spaces
     113                 :         for (++pos; pos < str.size() && isspace(str[pos]); ++pos)
     114                 :             ;
     115                 :         return str.substr(pos);
     116                 :     }
     117                 : }
     118                 : 
     119                 : template<> inline std::string Parser::parse< std::string >(
     120            1307 :     const std::string& def, const std::string& str) const
     121                 : {
     122            1307 :     if (str == std::string())
     123               0 :         return def;
     124            1307 :     return str;
     125                 : }
     126                 : 
     127                 : template<> inline int Parser::parse< int >(
     128               1 :     const int& def, const std::string& str) const
     129                 : {
     130               1 :         if (str == string())
     131               0 :                 return def;
     132               1 :         return (size_t)strtoul(str.c_str(), NULL, 10);
     133                 : }
     134                 : 
     135                 : struct Source : core::Source< Source, Setup, PropertyType >
     136               6 : {
     137                 :     AptDatabase &m_db;
     138                 : 
     139                 :     /* caching */
     140                 :     pkgCache::PkgFileIterator lastFile;
     141                 :     FileFd file;
     142                 :     size_t lastOffset;
     143                 : 
     144                 :     /* in-order retrieval of records, for InternalList */
     145                 :     typedef vector< pkgCache::VerFile * > VfList;
     146                 :     VfList m_vflist;
     147                 : 
     148            1742 :     VfList &vfList() {
     149            1742 :         if ( m_vflist.size() > 0 )
     150            1741 :             return m_vflist;
     151                 : 
     152               1 :         m_vflist.reserve(m_db.cache().HeaderP->PackageCount + 1);
     153                 : 
     154                 :         // Populate the vector of versions to print
     155            3778 :         for (pkgCache::PkgIterator pi = m_db.cache().PkgBegin(); !pi.end(); ++pi)
     156                 :         {
     157            3777 :             if (pi->VersionList == 0)
     158            1989 :                 continue;
     159                 : 
     160            3596 :             for( pkgCache::VerIterator vi = pi.VersionList(); !vi.end(); ++vi ) {
     161                 : 
     162                 :                 // Choose a valid file that contains the record for this version
     163            1808 :                 pkgCache::VerFileIterator vfi = vi.FileList();
     164            3181 :                 for ( ; !vfi.end(); ++vfi )
     165            1808 :                     if ((vfi.File()->Flags & pkgCache::Flag::NotSource) == 0)
     166             435 :                         break;
     167                 : 
     168            1808 :                 if ( !vfi.end() )
     169             435 :                     m_vflist.push_back( vfi );
     170                 :             }
     171                 :         }
     172                 : 
     173               1 :         sort(m_vflist.begin(), m_vflist.end(), localityCompare);
     174               1 :         return m_vflist;
     175                 :     }
     176                 : 
     177               6 :     Source( AptDatabase &db ) : m_db( db ) {}
     178                 : 
     179               2 :     InternalList listInternal() {
     180               2 :         return InternalList( *this );
     181                 :     }
     182                 : 
     183               5 :     Internal lookupToken( Token t ) {
     184               5 :         return m_db.lookupVersionFile( m_db.lookupVersion( t ) );
     185                 :     }
     186                 : 
     187                 :     // Sort a version list by package file locality
     188                 :     static bool localityCompare(const pkgCache::VerFile* a,
     189            4371 :                                 const pkgCache::VerFile* b)
     190                 :     {
     191            4371 :         if (a == 0 && b == 0)
     192               0 :             return false;
     193            4371 :         if (a == 0)
     194               0 :             return true;
     195            4371 :         if (b == 0)
     196               0 :             return false;
     197                 : 
     198            4371 :         if (a->File == b->File)
     199            4371 :             return a->Offset < b->Offset;
     200               0 :         return a->File < b->File;
     201                 :     }
     202                 : 
     203                 :     void invalidate() {
     204                 :         core::Source< Source, Setup, PropertyType >::invalidate();
     205                 :         lastFile = pkgCache::PkgFileIterator();
     206                 :     }
     207                 : 
     208            1311 :     std::string getRecord( Internal vfi ) {
     209            1311 :         if ( vfi.Cache() == 0 || vfi.end() )
     210               1 :             return "";
     211                 : 
     212            1310 :         if ((lastFile.Cache() == 0)
     213                 :             || vfi->File + m_db.cache().PkgFileP != lastFile)
     214                 :         {
     215                 :             lastFile = pkgCache::PkgFileIterator(
     216               5 :                 m_db.cache(), vfi->File + m_db.cache().PkgFileP);
     217               5 :             if (!lastFile.IsOk())
     218                 :                 throw wibble::exception::System(
     219                 :                     std::string("Reading the"
     220                 :                                 " data record for a package from file ")
     221               0 :                     + lastFile.FileName() );
     222               5 :             if (file.IsOpen())
     223               0 :                 file.Close();
     224               5 :             if (!file.Open(lastFile.FileName(), FileFd::ReadOnly))
     225                 :                 throw wibble::exception::System( std::string("Opening file ")
     226               0 :                                                  + lastFile.FileName() );
     227               5 :             lastOffset = 0;
     228                 :         }
     229                 : 
     230                 :         // If we start near were we ended, avoid a seek
     231                 :         // and enlarge the read a bit
     232            1310 :         size_t slack = vfi->Offset - lastOffset;
     233            1310 :         if ( slack > 128 ) // mornfall: was 8, making it 128
     234                 :         {
     235             871 :             slack = 0;
     236             871 :             if ( !file.Seek( vfi->Offset ) )
     237                 :                 throw wibble::exception::System(
     238                 :                     std::string("Cannot seek to package record in file ")
     239               0 :                     + lastFile.FileName() );
     240                 :         }
     241                 : 
     242            1310 :         char buffer[vfi->Size + slack + 1];
     243            1310 :         if (!file.Read(buffer, vfi->Size + slack))
     244                 :             throw wibble::exception::System(
     245                 :                 std::string("Cannot read package "
     246               0 :                             "record in file ") + lastFile.FileName() );
     247                 : 
     248            1310 :         buffer[vfi->Size + slack] = '\0';
     249                 :         //cerr << "Data read (slack: " << slack << ")" << endl;
     250                 : 
     251            1310 :         lastOffset = vfi->Offset + vfi->Size;
     252                 : 
     253            1310 :         return string(buffer+slack);
     254                 :     }
     255                 : 
     256             435 :     Token getToken( Internal i ) {
     257             435 :         Token t;
     258             435 :         t._id = getInternal< Name >( i ) + "_" + getInternal< Version >( i );
     259               0 :         return t;
     260                 :     }
     261                 : 
     262                 :     template< PropertyId p >
     263            1310 :     typename PropertyType< p >::T getInternal( Internal i ) {
     264            1310 :         Parser rec( getRecord( i ) );
     265            1310 :         return rec.get< p >();
     266                 :     }
     267                 : };
     268                 : 
     269               1 : template<> inline std::string Source::getInternal< Record >( Internal i ) {
     270               1 :     assert( !i.end() );
     271               1 :     return getRecord( i );
     272                 : }
     273                 : 
     274             870 : inline const Internal InternalList::head() const {
     275                 :     return pkgCache::VerFileIterator( m_source->m_db.cache(),
     276             870 :                                       m_source->vfList()[ m_idx ] );
     277                 : }
     278                 : 
     279             872 : inline bool InternalList::empty() const {
     280             872 :     return m_idx == m_source->vfList().size();
     281                 : }
     282                 : 
     283                 : 
     284                 : }
     285                 : }
     286                 : }
     287                 : 
     288                 : #endif

Generated by: LTP GCOV extension version 1.6