LTP GCOV extension - code coverage report
Current view: directory - ept/debtags/maint - vocabularymerger.cc
Test: lcov.info
Date: 2008-08-14 Instrumented lines: 181
Code covered: 81.2 % Executed lines: 147

       1                 : /*
       2                 :  * Merge different vocabularies together and create the tag and facet indexes
       3                 :  *
       4                 :  * Copyright (C) 2003-2006  Enrico Zini <enrico@debian.org>
       5                 :  *
       6                 :  * This program is free software; you can redistribute it and/or modify
       7                 :  * it under the terms of the GNU General Public License as published by
       8                 :  * the Free Software Foundation; either version 2 of the License, or
       9                 :  * (at your option) any later version.
      10                 :  *
      11                 :  * This program is distributed in the hope that it will be useful,
      12                 :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :  * GNU General Public License for more details.
      15                 :  *
      16                 :  * You should have received a copy of the GNU General Public License
      17                 :  * along with this program; if not, write to the Free Software
      18                 :  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      19                 :  */
      20                 : 
      21                 : 
      22                 : #include <ept/debtags/maint/vocabularymerger.h>
      23                 : #include <ept/debtags/maint/debdbparser.h>
      24                 : 
      25                 : #include <cassert>
      26                 : #include <cstring>
      27                 : 
      28                 : using namespace std;
      29                 : using namespace tagcoll;
      30                 : 
      31                 : namespace ept {
      32                 : namespace debtags {
      33                 : 
      34            1432 : static void writeDebStyleField(FILE* out, const string& name, const string& val) throw ()
      35                 : {
      36            1432 :         fprintf(out, "%s: ", name.c_str());
      37                 : 
      38                 :         // Properly escape newlines
      39            1432 :         bool was_nl = false;
      40           56225 :         for (string::const_iterator s = val.begin(); s != val.end(); s++)
      41           54793 :                 if (was_nl)
      42                 :                         // \n\n -> \n .\n
      43             738 :                         if (*s == '\n')
      44                 :                         {
      45             120 :                                 fputc(' ', out);
      46             120 :                                 fputc('.', out);
      47             120 :                                 fputc(*s, out);
      48                 :                         }
      49                 :                         // \n([^ \t]) -> \n \1
      50             618 :                         else if (*s != ' ' && *s != '\t')
      51                 :                         {
      52             618 :                                 fputc(' ', out);
      53             618 :                                 fputc(*s, out);
      54             618 :                                 was_nl = false;
      55                 :                         }
      56                 :                         // \n[ \t] goes unchanged
      57                 :                         else
      58                 :                         {
      59               0 :                                 fputc(*s, out);
      60               0 :                                 was_nl = false;
      61                 :                         }
      62                 :                 else
      63           54055 :                         if (*s == '\n')
      64                 :                         {
      65             618 :                                 fputc(*s, out);
      66             618 :                                 was_nl = true;
      67                 :                         }
      68                 :                         else
      69           53437 :                                 fputc(*s, out);
      70                 : 
      71            1432 :         fputc('\n', out);
      72            1432 : }
      73                 : 
      74            1865 : VocabularyMerger::TagData& VocabularyMerger::FacetData::obtainTag(const std::string& name)
      75                 : {
      76            1865 :         std::map<std::string, TagData>::iterator i = tags.find(name);
      77            1865 :         if (i == tags.end())
      78                 :         {
      79                 :                 // Create the tag if it's missing
      80            1245 :                 pair<std::map<std::string, TagData>::iterator, bool> res = tags.insert(make_pair<std::string, TagData>(name, TagData()));
      81            1245 :                 i = res.first;
      82            1245 :                 i->second.name = name;
      83                 :         }
      84            1865 :         return i->second;
      85                 : }
      86                 : 
      87            1953 : VocabularyMerger::FacetData& VocabularyMerger::obtainFacet(const std::string& name)
      88                 : {
      89            1953 :         std::map<std::string, FacetData>::iterator i = facets.find(name);
      90            1953 :         if (i == facets.end())
      91                 :         {
      92                 :                 // Create the facet if it's missing
      93              62 :                 pair<std::map<std::string, FacetData>::iterator, bool> res = facets.insert(make_pair<std::string, FacetData>(name, FacetData()));
      94              62 :                 i = res.first;
      95              62 :                 i->second.name = name;
      96                 :         }
      97            1953 :         return i->second;
      98                 : }
      99                 : 
     100            1865 : VocabularyMerger::TagData& VocabularyMerger::obtainTag(const std::string& fullname)
     101                 : {
     102            1865 :         size_t p = fullname.find("::");
     103            1865 :         if (p == string::npos)
     104                 :         {
     105              28 :                 FacetData& facet = obtainFacet("legacy");
     106              28 :                 return facet.obtainTag(fullname);
     107                 :         } else {
     108            1837 :                 FacetData& facet = obtainFacet(fullname.substr(0, p));
     109            3674 :                 return facet.obtainTag(fullname.substr(p + 2));
     110                 :         }
     111                 : }
     112                 : 
     113                 : 
     114               7 : void VocabularyMerger::read(tagcoll::input::Input& input)
     115                 : {
     116               7 :         DebDBParser parser(input);
     117               7 :         DebDBParser::Record record;
     118                 : 
     119            1967 :         while (parser.nextRecord(record))
     120                 :         {
     121            1953 :                 DebDBParser::Record::const_iterator fi = record.find("Facet");
     122            3906 :                 DebDBParser::Record::const_iterator ti = record.find("Tag");
     123            3906 :                 if (fi != record.end())
     124                 :                 {
     125                 :                         // Get the facet record
     126              88 :                         FacetData& facet = obtainFacet(fi->second);
     127                 :                         //fprintf(stderr, "Read facet@%d %.*s\n", parser.lineNumber(), PFSTR(facet.name));
     128              88 :                         assert(facet.name == fi->second);
     129                 : 
     130                 :                         // Merge the data
     131             416 :                         for (DebDBParser::Record::const_iterator i = record.begin();
     132                 :                                         i != record.end(); i++)
     133             328 :                                 if (i->first != "Facet")
     134             240 :                                         facet[i->first] = i->second;
     135                 :                 }
     136            1865 :                 else if (ti != record.end())
     137                 :                 {
     138                 :                         // Get the tag record
     139            1865 :                         TagData& tag = obtainTag(ti->second);
     140                 :                         //fprintf(stderr, "Read tag@%d %.*s\n", parser.lineNumber(), PFSTR(tag.name));
     141                 :                         //assert(tag.name == ti->second);
     142                 : 
     143                 :                         // Merge the data
     144            5796 :                         for (DebDBParser::Record::const_iterator i = record.begin();
     145                 :                                         i != record.end(); i++)
     146            3931 :                                 if (i->first != "Tag")
     147            2066 :                                         tag[i->first] = i->second;
     148                 :                 }
     149                 :                 else
     150                 :                 {
     151                 :                         fprintf(stderr, "%s:%d: Skipping record without Tag or Facet field\n",
     152               0 :                                         input.fileName().c_str(), input.lineNumber());
     153                 :                 }
     154               7 :         }
     155               7 : }
     156                 : 
     157               0 : bool VocabularyMerger::hasTag(const std::string& fullname) const
     158                 : {
     159               0 :         size_t p = fullname.find("::");
     160               0 :         std::string facetName;
     161               0 :         std::string tagName;
     162               0 :         if (p == string::npos)
     163                 :         {
     164               0 :                 facetName = "legacy";
     165               0 :                 tagName = fullname;
     166                 :         } else {
     167               0 :                 facetName = fullname.substr(0, p);
     168               0 :                 tagName = fullname.substr(p + 2);
     169                 :         }
     170                 : 
     171               0 :         std::map<std::string, FacetData>::const_iterator i = facets.find(facetName);
     172               0 :         if (i == facets.end())
     173               0 :                 return false;
     174               0 :         return i->second.tags.find(tagName) != i->second.tags.end();
     175                 : }
     176                 : 
     177               0 : int VocabularyMerger::tagID(const std::string& fullname) const
     178                 : {
     179               0 :         size_t p = fullname.find("::");
     180               0 :         std::string facetName;
     181               0 :         std::string tagName;
     182               0 :         if (p == string::npos)
     183                 :         {
     184               0 :                 facetName = "legacy";
     185               0 :                 tagName = fullname;
     186                 :         } else {
     187               0 :                 facetName = fullname.substr(0, p);
     188               0 :                 tagName = fullname.substr(p + 2);
     189                 :         }
     190                 : 
     191               0 :         std::map<std::string, FacetData>::const_iterator i = facets.find(facetName);
     192               0 :         if (i == facets.end())
     193               0 :                 return -1;
     194               0 :         std::map<std::string, TagData>::const_iterator j = i->second.tags.find(tagName);
     195               0 :         if (j == i->second.tags.end())
     196               0 :                 return -1;
     197               0 :         return j->second.id;
     198                 : }
     199                 : 
     200               1 : std::set<std::string> VocabularyMerger::tagNames() const
     201                 : {
     202               1 :         set<string> res;
     203              30 :         for (std::map<std::string, FacetData>::const_iterator f = facets.begin(); f != facets.end(); f++)
     204             649 :                 for (std::map<std::string, TagData>::const_iterator t = f->second.tags.begin();
     205                 :                                 t != f->second.tags.end(); t++)
     206             620 :                         res.insert(f->first + "::" + t->first);
     207               0 :         return res;
     208                 : }
     209                 : 
     210               4 : void VocabularyMerger::write(const std::string& fname)
     211                 : {
     212               4 :         FILE* out = fopen(fname.c_str(), "wt");
     213               4 :         if (!out)
     214               0 :                 throw wibble::exception::File(fname, "cept_debtags_vocabularymerger:reating file ");
     215               4 :         write(out);
     216               4 :         fclose(out);
     217               4 : }
     218                 : 
     219               4 : void VocabularyMerger::write(FILE* out)
     220                 : {
     221               4 :         long start_ofs = ftell(out);
     222               4 :         int facetid = 0;
     223               4 :         int tagid = 0;
     224                 : 
     225                 :         //fprintf(stderr, "Write\n");
     226              37 :         for (std::map<std::string, FacetData>::iterator f = facets.begin(); f != facets.end(); f++)
     227                 :         {
     228              33 :                 f->second.id = facetid++;
     229                 :                 //fprintf(stderr, "Writing facet %.*s\n", PFSTR(f->first));
     230              33 :                 f->second.ofs = ftell(out) - start_ofs;
     231              33 :                 writeDebStyleField(out, "Facet", f->first);
     232             115 :                 for (std::map<std::string, std::string>::const_iterator j = f->second.begin();
     233                 :                                 j != f->second.end(); j++)
     234              82 :                         writeDebStyleField(out, j->first, j->second);
     235              33 :                 fputc('\n', out);
     236              33 :                 f->second.len = ftell(out) - f->second.ofs;
     237                 : 
     238             658 :                 for (std::map<std::string, TagData>::iterator t = f->second.tags.begin();
     239                 :                                 t != f->second.tags.end(); t++)
     240                 :                 {
     241             625 :                         t->second.id = tagid++;
     242                 :                         //fprintf(stderr, "Writing tag %.*s\n", PFSTR(t->first));
     243             625 :                         t->second.ofs = ftell(out) - start_ofs;
     244             625 :                         writeDebStyleField(out, "Tag", f->first + "::" + t->first);
     245            1317 :                         for (std::map<std::string, std::string>::const_iterator j = t->second.begin();
     246                 :                                         j != t->second.end(); j++)
     247             692 :                                 writeDebStyleField(out, j->first, j->second);
     248             625 :                         fputc('\n', out);
     249             625 :                         t->second.len = ftell(out) - t->second.ofs;
     250                 :                 }
     251                 :         }
     252                 : 
     253               4 :         tagCount = tagid;
     254               4 : }
     255                 : 
     256                 : 
     257               4 : int VocabularyMerger::FacetIndexer::encodedSize() const 
     258                 : {
     259                 :         // First the main offset table
     260               4 :         int size = vm.facets.size() * sizeof(int);
     261                 : 
     262              37 :         for (std::map<std::string, FacetData>::const_iterator f = vm.facets.begin(); f != vm.facets.end(); f++)
     263                 :         {
     264                 :                 // offset of record in vocabulary
     265                 :                 // size of record in vocabulary
     266                 :                 // id of first tag
     267                 :                 // id of last tag
     268                 :                 // name (0-terminated)
     269              33 :                 size += 4 * sizeof(int) + f->first.size() + 1;
     270                 :                 
     271                 :                 // Align to int boundaries
     272              33 :                 if ((size % sizeof(int)) != 0)
     273              25 :                         size = (size + sizeof(int)) / sizeof(int) * sizeof(int);
     274                 :         }
     275                 : 
     276               4 :         return tagcoll::diskindex::MMap::align(size);
     277                 : }
     278                 : 
     279               4 : void VocabularyMerger::FacetIndexer::encode(char* buf) const 
     280                 : {
     281               4 :         int pos = vm.facets.size() * sizeof(int);
     282                 : 
     283              37 :         for (std::map<std::string, FacetData>::const_iterator f = vm.facets.begin(); f != vm.facets.end(); f++)
     284                 :         {
     285              33 :                 ((int*)buf)[f->second.id] = pos;
     286                 : 
     287                 :                 // offset of record in vocabulary
     288              33 :                 *(int*)(buf+pos) = f->second.ofs;
     289              33 :                 pos += sizeof(int);
     290                 : 
     291                 :                 // size of record in vocabulary
     292              33 :                 *(int*)(buf+pos) = f->second.len;
     293              33 :                 pos += sizeof(int);
     294                 : 
     295              33 :                 if (f->second.tags.empty())
     296                 :                 {
     297                 :                         // id of first tag
     298               1 :                         *(int*)(buf+pos) = -1;
     299               1 :                         pos += sizeof(int);
     300                 : 
     301                 :                         // id of last tag
     302               1 :                         *(int*)(buf+pos) = -1;
     303               1 :                         pos += sizeof(int);
     304                 :                 } else {
     305                 :                         // id of first tag
     306              32 :                         *(int*)(buf+pos) = f->second.tags.begin()->second.id;
     307              32 :                         pos += sizeof(int);
     308                 : 
     309                 :                         // id of last tag
     310              32 :                         *(int*)(buf+pos) = f->second.tags.rbegin()->second.id;
     311              32 :                         pos += sizeof(int);
     312                 :                 }
     313                 : 
     314                 :                 // name (0-terminated)
     315              33 :                 memcpy(buf + pos, f->first.c_str(), f->first.size() + 1);
     316              33 :                 pos += f->first.size() + 1;
     317                 :                 
     318                 :                 // Align to int boundaries
     319              33 :                 if ((pos % sizeof(int)) != 0)
     320              25 :                         pos = (pos + sizeof(int)) / sizeof(int) * sizeof(int);
     321                 :         }
     322               4 : }
     323                 : 
     324               4 : int VocabularyMerger::TagIndexer::encodedSize() const 
     325                 : {
     326                 :         // First the main offset table
     327               4 :         int size = vm.tagCount * sizeof(int);
     328                 : 
     329              37 :         for (std::map<std::string, FacetData>::const_iterator f = vm.facets.begin(); f != vm.facets.end(); f++)
     330                 :         {
     331             658 :                 for (std::map<std::string, TagData>::const_iterator t = f->second.tags.begin();
     332                 :                                 t != f->second.tags.end(); t++)
     333                 :                 {
     334                 :                         // offset of record in vocabulary
     335                 :                         // size of record in vocabulary
     336                 :                         // id of facet
     337                 :                         // name (0-terminated)
     338             625 :                         size += 3 * sizeof(int) + f->first.size() + t->first.size() + 3;
     339                 :                 
     340                 :                         // Align to int boundaries
     341             625 :                         if ((size % sizeof(int)) != 0)
     342             479 :                                 size = (size + sizeof(int)) / sizeof(int) * sizeof(int);
     343                 :                 }
     344                 :         }
     345               4 :         return tagcoll::diskindex::MMap::align(size);
     346                 : }
     347                 : 
     348               4 : void VocabularyMerger::TagIndexer::encode(char* buf) const 
     349                 : {
     350               4 :         int pos = vm.tagCount * sizeof(int);
     351                 : 
     352              37 :         for (std::map<std::string, FacetData>::const_iterator f = vm.facets.begin(); f != vm.facets.end(); f++)
     353                 :         {
     354             658 :                 for (std::map<std::string, TagData>::const_iterator t = f->second.tags.begin();
     355                 :                                 t != f->second.tags.end(); t++)
     356                 :                 {
     357             625 :                         ((int*)buf)[t->second.id] = pos;
     358                 : 
     359                 :                         // offset of record in vocabulary
     360             625 :                         *(int*)(buf+pos) = t->second.ofs;
     361             625 :                         pos += sizeof(int);
     362                 : 
     363                 :                         // size of record in vocabulary
     364             625 :                         *(int*)(buf+pos) = t->second.len;
     365             625 :                         pos += sizeof(int);
     366                 : 
     367                 :                         // id of facet
     368             625 :                         *(int*)(buf+pos) = f->second.id;
     369             625 :                         pos += sizeof(int);
     370                 : 
     371                 :                         // name (0-terminated)
     372             625 :                         string name = f->first + "::" + t->first;
     373             625 :                         memcpy(buf + pos, name.c_str(), name.size() + 1);
     374             625 :                         pos += name.size() + 1;
     375                 :                         
     376                 :                         // Align to int boundaries
     377             625 :                         if ((pos % sizeof(int)) != 0)
     378             479 :                                 pos = (pos + sizeof(int)) / sizeof(int) * sizeof(int);
     379                 :                 }
     380                 :         }
     381               4 : }
     382                 : 
     383                 : }
     384               6 : }
     385                 : 
     386                 : // vim:set ts=4 sw=4:

Generated by: LTP GCOV extension version 1.6