LCOV - lcov.info - ept/core/apt/record.h

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