LCOV - lcov.info - ept/core/apt/recordparser.cpp

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

           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/core/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 core {
          34                 : namespace record {
          35                 :
          36                 : struct rpcompare
          37                 : {
          38                 :         const RecordParser& rp;
          39            1310 :         rpcompare(const RecordParser& rp) : rp(rp) {}
          40           89600 :         bool operator()(size_t a, size_t b)
          41                 :         {
          42           89600 :                 return rp.name(a) < rp.name(b);
          43                 :         }
          44                 : };
          45                 :
          46            1310 : void RecordParser::scan(const std::string& str)
          47                 : {
          48            1310 :         buffer = str;
          49            1310 :         ends.clear();
          50            1310 :         sorted.clear();
          51                 :
          52                 :         //cerr << "PARSE " << endl << buffer << "*****" << endl;
          53                 :
          54                 :         // Scan the buffer, taking note of all ending offsets of the various fields
          55            1310 :         size_t pos = 0;
          56            1310 :         size_t idx = 0;
          57           29815 :         while (pos < buffer.size() - 1)
          58                 :         {
          59                 :                 //cerr << "PREPOS " << pos << " left: " << buffer.substr(pos, 10) << endl;
          60           28505 :                 pos = buffer.find("\n", pos);
          61                 :                 //cerr << "POSTPOS " << pos << " left: " << (pos == string::npos ? "NONE" : buffer.substr(pos, 10)) << endl;
          62                 :
          63                 :                 // The buffer does not end with a newline
          64           28505 :                 if (pos == string::npos)
          65                 :                 {
          66                 :                         //cerr << "ENDNOTEOL" << endl;
          67               1 :                         pos = buffer.size();
          68               1 :                         ends.push_back(pos);
          69               1 :                         sorted.push_back(idx++);
          70               1 :                         break;
          71                 :                 }
          72                 :
          73           28504 :                 ++pos;
          74                 :                 //cerr << "POSTPOSINC " << pos << " left: " << buffer.substr(pos, 10) << endl;
          75                 :
          76                 :                 // The buffer ends with a newline
          77           28504 :                 if (pos == buffer.size())
          78                 :                 {
          79                 :                         //cerr << "ENDEOL" << endl;
          80            1309 :                         ends.push_back(pos);
          81            1309 :                         sorted.push_back(idx++);
          82            1309 :                         break;
          83                 :                 }
          84                 :
          85                 :                 // Terminate parsing on double newlines
          86           27195 :                 if (buffer[pos] == '\n')
          87                 :                 {
          88                 :                         //cerr << "ENDDOUBLENL" << endl;
          89               0 :                         ends.push_back(pos);
          90               0 :                         sorted.push_back(idx++);
          91               0 :                         break;
          92                 :                 }
          93                 :
          94                 :                 // Mark the end of the field if it's not a continuation line
          95           27195 :                 if (!isspace(buffer[pos]))
          96                 :                 {
          97                 :                         //cerr << "INNERFIELD" << endl;
          98           17224 :                         ends.push_back(pos);
          99           17224 :                         sorted.push_back(idx++);
         100                 :                 } //else
         101                 :                         //cerr << "CONTLINE" << endl;
         102                 :         }
         103                 :
         104                 :         // Sort the sorted array
         105            1310 :         sort(sorted.begin(), sorted.end(), rpcompare(*this));
         106                 :
         107                 :         //for (size_t i = 0; i < ends.size(); ++i)
         108                 :         //      cerr << ends[i] << "\t" << name(i) << "\t" << sorted[i] << "\t" << name(sorted[i]) << endl;
         109            1310 : }
         110                 :
         111          187124 : std::string RecordParser::field(size_t idx) const
         112                 : {
         113          187124 :         if (idx >= ends.size())
         114               1 :                 return string();
         115          187123 :         if (idx == 0)
         116           16577 :                 return buffer.substr(0, ends[0]);
         117                 :         else
         118          170546 :                 return buffer.substr(ends[idx-1], ends[idx]-ends[idx-1]);
         119                 : }
         120                 :
         121          185814 : std::string RecordParser::name(size_t idx) const
         122                 : {
         123          185814 :         string res = field(idx);
         124          185814 :         size_t pos = res.find(":");
         125          185814 :         if (pos == string::npos)
         126               2 :                 return res;
         127          185812 :         return res.substr(0, pos);
         128                 : }
         129                 :
         130            1310 : std::string RecordParser::lookup(size_t idx) const
         131                 : {
         132            1310 :         string res = field(idx);
         133            1310 :         size_t pos = res.find(":");
         134            1310 :         if (pos == string::npos)
         135               1 :                 return res;
         136                 :         // Skip initial whitespace after the :
         137            1309 :         for (++pos; pos < res.size() && isspace(res[pos]); ++pos)
         138                 :                 ;
         139            1309 :         res = res.substr(pos);
         140                 :         // Trim spaces at the end
         141            3927 :         while (!res.empty() && isspace(res[res.size() - 1]))
         142            1309 :                 res.resize(res.size() - 1);
         143            1309 :         return res;
         144                 : }
         145                 :
         146            1310 : size_t RecordParser::index(const std::string& str) const
         147                 : {
         148                 :         int begin, end;
         149                 :
         150                 :         /* Binary search */
         151            1310 :         begin = -1, end = size();
         152            7924 :         while (end - begin > 1)
         153                 :         {
         154            5304 :                 int cur = (end + begin) / 2;
         155                 :                 //cerr << "Test " << cur << " " << str << " < " << name(cur) << endl;
         156            5304 :                 if (name(sorted[cur]) > str)
         157            1724 :                         end = cur;
         158                 :                 else
         159            3580 :                         begin = cur;
         160                 :         }
         161                 :
         162            1310 :         if (begin == -1 || name(sorted[begin]) != str)
         163               1 :                 return size();
         164                 :         else
         165            1309 :                 return sorted[begin];
         166                 : }
         167                 :
         168                 : }
         169                 : }
         170                 : }
         171                 :
         172                 : // vim:set ts=4 sw=4:

Generated by: LTP GCOV extension version 1.6