LCOV - lcov.info - ept/apt/recordparser.cc

LTP GCOV extension - code coverage report
Current view: | directory - ept/apt - recordparser.cc
Test: | lcov.info
Date: | 2008-08-14 |  | Instrumented lines: | 62
Code covered: | 100.0 % |  | Executed lines: | 62

           1                 : /** \file
           2                 :  * Parser for APT records
           3                 :  */
           4                 :
           5                 : /*
           6                 :  * Copyright (C) 2007  Enrico Zini <enrico@enricozini.org>
           7                 :  *
           8                 :  * This library is free software; you can redistribute it and/or
           9                 :  * modify it under the terms of the GNU Lesser General Public
          10                 :  * License as published by the Free Software Foundation; either
          11                 :  * version 2.1 of the License, or (at your option) any later version.
          12                 :  *
          13                 :  * This library is distributed in the hope that it will be useful,
          14                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
          15                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
          16                 :  * Lesser General Public License for more details.
          17                 :  *
          18                 :  * You should have received a copy of the GNU Lesser General Public
          19                 :  * License along with this library; if not, write to the Free Software
          20                 :  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
          21                 :  */
          22                 :
          23                 : #include <ept/apt/recordparser.h>
          24                 :
          25                 : #include <algorithm>
          26                 : #include <cctype>
          27                 :
          28                 : //#include <iostream>
          29                 :
          30                 : using namespace std;
          31                 :
          32                 : namespace ept {
          33                 : namespace apt {
          34                 :
          35                 : struct rpcompare
          36                 : {
          37                 :         const RecordParser& rp;
          38            2618 :         rpcompare(const RecordParser& rp) : rp(rp) {}
          39          177724 :         bool operator()(size_t a, size_t b)
          40                 :         {
          41          177724 :                 return rp.name(a) < rp.name(b);
          42                 :         }
          43                 : };
          44                 :
          45            2618 : void RecordParser::scan(const std::string& str)
          46                 : {
          47            2618 :         buffer = str;
          48            2618 :         ends.clear();
          49            2618 :         sorted.clear();
          50                 :
          51                 :         //cerr << "PARSE " << endl << buffer << "*****" << endl;
          52                 :
          53                 :         // Scan the buffer, taking note of all ending offsets of the various fields
          54            2618 :         size_t pos = 0;
          55            2618 :         size_t idx = 0;
          56           59427 :         while (pos < buffer.size() - 1)
          57                 :         {
          58                 :                 //cerr << "PREPOS " << pos << " left: " << buffer.substr(pos, 10) << endl;
          59           56809 :                 pos = buffer.find("\n", pos);
          60                 :                 //cerr << "POSTPOS " << pos << " left: " << (pos == string::npos ? "NONE" : buffer.substr(pos, 10)) << endl;
          61                 :
          62                 :                 // The buffer does not end with a newline
          63           56809 :                 if (pos == string::npos)
          64                 :                 {
          65                 :                         //cerr << "ENDNOTEOL" << endl;
          66               1 :                         pos = buffer.size();
          67               1 :                         ends.push_back(pos);
          68               1 :                         sorted.push_back(idx++);
          69               1 :                         break;
          70                 :                 }
          71                 :
          72           56808 :                 ++pos;
          73                 :                 //cerr << "POSTPOSINC " << pos << " left: " << buffer.substr(pos, 10) << endl;
          74                 :
          75                 :                 // The buffer ends with a newline
          76           56808 :                 if (pos == buffer.size())
          77                 :                 {
          78                 :                         //cerr << "ENDEOL" << endl;
          79              11 :                         ends.push_back(pos);
          80              11 :                         sorted.push_back(idx++);
          81              11 :                         break;
          82                 :                 }
          83                 :
          84                 :                 // Terminate parsing on double newlines
          85           56797 :                 if (buffer[pos] == '\n')
          86                 :                 {
          87                 :                         //cerr << "ENDDOUBLENL" << endl;
          88            2606 :                         ends.push_back(pos);
          89            2606 :                         sorted.push_back(idx++);
          90            2606 :                         break;
          91                 :                 }
          92                 :
          93                 :                 // Mark the end of the field if it's not a continuation line
          94           54191 :                 if (!isspace(buffer[pos]))
          95                 :                 {
          96                 :                         //cerr << "INNERFIELD" << endl;
          97           34233 :                         ends.push_back(pos);
          98           34233 :                         sorted.push_back(idx++);
          99                 :                 } //else
         100                 :                         //cerr << "CONTLINE" << endl;
         101                 :         }
         102                 :
         103                 :         // Sort the sorted array
         104            2618 :         sort(sorted.begin(), sorted.end(), rpcompare(*this));
         105                 :
         106                 :         //for (size_t i = 0; i < ends.size(); ++i)
         107                 :         //      cerr << ends[i] << "\t" << name(i) << "\t" << sorted[i] << "\t" << name(sorted[i]) << endl;
         108            2618 : }
         109                 :
         110          465183 : std::string RecordParser::field(size_t idx) const
         111                 : {
         112          465183 :         if (idx >= ends.size())
         113            2664 :                 return string();
         114          462519 :         if (idx == 0)
         115           52771 :                 return buffer.substr(0, ends[0]);
         116                 :         else
         117          409748 :                 return buffer.substr(ends[idx-1], ends[idx]-ends[idx-1]);
         118                 : }
         119                 :
         120          446879 : std::string RecordParser::name(size_t idx) const
         121                 : {
         122          446879 :         string res = field(idx);
         123          446879 :         size_t pos = res.find(":");
         124          446879 :         if (pos == string::npos)
         125               1 :                 return res;
         126          446878 :         return res.substr(0, pos);
         127                 : }
         128                 :
         129           18279 : std::string RecordParser::lookup(size_t idx) const
         130                 : {
         131           18279 :         string res = field(idx);
         132           18279 :         size_t pos = res.find(":");
         133           18279 :         if (pos == string::npos)
         134            2662 :                 return res;
         135                 :         // Skip initial whitespace after the :
         136           15617 :         for (++pos; pos < res.size() && isspace(res[pos]); ++pos)
         137                 :                 ;
         138           15617 :         res = res.substr(pos);
         139                 :         // Trim spaces at the end
         140           46850 :         while (!res.empty() && isspace(res[res.size() - 1]))
         141           15616 :                 res.resize(res.size() - 1);
         142           15617 :         return res;
         143                 : }
         144                 :
         145           18283 : size_t RecordParser::index(const std::string& str) const
         146                 : {
         147                 :         int begin, end;
         148                 :
         149                 :         /* Binary search */
         150           18283 :         begin = -1, end = size();
         151          109703 :         while (end - begin > 1)
         152                 :         {
         153           73137 :                 int cur = (end + begin) / 2;
         154                 :                 //cerr << "Test " << cur << " " << str << " < " << name(cur) << endl;
         155           73137 :                 if (name(sorted[cur]) > str)
         156           32507 :                         end = cur;
         157                 :                 else
         158           40630 :                         begin = cur;
         159                 :         }
         160                 :
         161           18283 :         if (begin == -1 || name(sorted[begin]) != str)
         162            2661 :                 return size();
         163                 :         else
         164           15622 :                 return sorted[begin];
         165                 : }
         166                 :
         167                 : }
         168                 : }
         169                 :
         170                 : // vim:set ts=4 sw=4:

Generated by: LTP GCOV extension version 1.6