LCOV - code coverage report
Current view: top level - net - serialise.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 200 217 92.2 %
Date: 2011-08-21 Functions: 11 11 100.0 %
Branches: 50 60 83.3 %

           Branch data     Line data    Source code
       1                 :            : /** @file serialise.cc
       2                 :            :  * @brief functions to convert Xapian objects to strings and back
       3                 :            :  */
       4                 :            : /* Copyright (C) 2006,2007,2008,2009,2010 Olly Betts
       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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
      19                 :            :  */
      20                 :            : 
      21                 :            : #include <config.h>
      22                 :            : 
      23                 :            : #include <xapian/document.h>
      24                 :            : #include <xapian/error.h>
      25                 :            : #include <xapian/positioniterator.h>
      26                 :            : #include <xapian/termiterator.h>
      27                 :            : #include <xapian/valueiterator.h>
      28                 :            : 
      29                 :            : #include "omassert.h"
      30                 :            : #include "omenquireinternal.h"
      31                 :            : #include "serialise.h"
      32                 :            : #include "serialise-double.h"
      33                 :            : #include "utils.h"
      34                 :            : #include "weightinternal.h"
      35                 :            : 
      36                 :            : #include <string>
      37                 :            : #include <cstring>
      38                 :            : 
      39                 :            : using namespace std;
      40                 :            : 
      41                 :            : size_t
      42                 :   12357257 : decode_length(const char ** p, const char *end, bool check_remaining)
      43                 :            : {
      44         [ -  + ]:   12357257 :     if (*p == end) {
      45                 :          0 :         throw Xapian::NetworkError("Bad encoded length: no data");
      46                 :            :     }
      47                 :            : 
      48                 :   12357257 :     size_t len = static_cast<unsigned char>(*(*p)++);
      49         [ +  + ]:   12357257 :     if (len == 0xff) {
      50                 :     859006 :         len = 0;
      51                 :            :         unsigned char ch;
      52                 :     859006 :         int shift = 0;
      53         [ +  + ]:    2059261 :         do {
      54 [ +  - ][ -  + ]:    2059261 :             if (*p == end || shift > 28)
      55                 :          0 :                 throw Xapian::NetworkError("Bad encoded length: insufficient data");
      56                 :    2059261 :             ch = *(*p)++;
      57                 :    2059261 :             len |= size_t(ch & 0x7f) << shift;
      58                 :    2059261 :             shift += 7;
      59                 :            :         } while ((ch & 0x80) == 0);
      60                 :     859006 :         len += 255;
      61                 :            :     }
      62 [ +  + ][ +  + ]:   12357257 :     if (check_remaining && len > size_t(end - *p)) {
      63                 :         15 :         throw Xapian::NetworkError("Bad encoded length: length greater than data");
      64                 :            :     }
      65                 :   12357242 :     return len;
      66                 :            : }
      67                 :            : 
      68                 :            : string
      69                 :      54533 : serialise_error(const Xapian::Error &e)
      70                 :            : {
      71                 :      54533 :     string result;
      72                 :      54533 :     result += encode_length(strlen(e.get_type()));
      73                 :      54533 :     result += e.get_type();
      74                 :      54533 :     result += encode_length(e.get_context().length());
      75                 :      54533 :     result += e.get_context();
      76                 :      54533 :     result += encode_length(e.get_msg().length());
      77                 :      54533 :     result += e.get_msg();
      78                 :            :     // The "error string" goes last so we don't need to store its length.
      79                 :      54533 :     const char * err = e.get_error_string();
      80         [ +  + ]:      54533 :     if (err) result += err;
      81                 :          0 :     return result;
      82                 :            : }
      83                 :            : 
      84                 :            : void
      85                 :      54527 : unserialise_error(const string &serialised_error, const string &prefix,
      86                 :            :                   const string &new_context)
      87                 :            : {
      88                 :            :     // Use c_str() so last string is nul-terminated.
      89                 :      54527 :     const char * p = serialised_error.c_str();
      90                 :      54527 :     const char * end = p + serialised_error.size();
      91                 :            :     size_t len;
      92                 :      54527 :     len = decode_length(&p, end, true);
      93   [ -  +  #  # ]:      54527 :     if (len == 7 && memcmp(p, "UNKNOWN", 7) == 0) {
      94                 :          0 :         throw Xapian::InternalError("UNKNOWN");
      95                 :            :     }
      96                 :      54527 :     string type(p, len);
      97                 :      54527 :     p += len;
      98                 :            : 
      99                 :      54527 :     len = decode_length(&p, end, true);
     100                 :      54527 :     string context(p, len);
     101                 :      54527 :     p += len;
     102                 :            : 
     103                 :      54527 :     len = decode_length(&p, end, true);
     104                 :      54527 :     string msg(prefix);
     105                 :      54527 :     msg.append(p, len);
     106                 :      54527 :     p += len;
     107                 :            : 
     108         [ +  + ]:      54527 :     const char * error_string = (p == end) ? NULL : p;
     109                 :            : 
     110 [ -  + ][ #  # ]:      54527 :     if (!context.empty() && !new_context.empty()) {
                 [ -  + ]
     111                 :          0 :         msg += "; context was: ";
     112                 :          0 :         msg += context;
     113                 :          0 :         context = new_context;
     114                 :            :     }
     115                 :            : 
     116                 :            : #include <xapian/errordispatch.h>
     117                 :            : 
     118                 :          0 :     string newmsg = "Unknown remote exception type ";
     119                 :          0 :     newmsg += type;
     120                 :          0 :     newmsg += ": ";
     121                 :          0 :     newmsg += msg;
     122                 :     163581 :     throw Xapian::InternalError(newmsg, context);
     123                 :            : }
     124                 :            : 
     125                 :            : string
     126                 :       8808 : serialise_stats(const Xapian::Weight::Internal &stats)
     127                 :            : {
     128                 :       8808 :     string result;
     129                 :            : 
     130                 :       8808 :     result += encode_length(stats.total_length);
     131                 :       8808 :     result += encode_length(stats.collection_size);
     132                 :       8808 :     result += encode_length(stats.rset_size);
     133                 :            : 
     134                 :       8808 :     result += encode_length(stats.termfreqs.size());
     135                 :       8808 :     map<string, TermFreqs>::const_iterator i;
     136         [ +  + ]:      19908 :     for (i = stats.termfreqs.begin(); i != stats.termfreqs.end(); ++i) {
     137                 :      11100 :         result += encode_length(i->first.size());
     138                 :      11100 :         result += i->first;
     139                 :      11100 :         result += encode_length(i->second.termfreq);
     140         [ +  + ]:      11100 :         if (stats.rset_size != 0)
     141                 :        234 :             result += encode_length(i->second.reltermfreq);
     142                 :            :     }
     143                 :            : 
     144                 :          0 :     return result;
     145                 :            : }
     146                 :            : 
     147                 :            : Xapian::Weight::Internal
     148                 :       8808 : unserialise_stats(const string &s)
     149                 :            : {
     150                 :       8808 :     const char * p = s.data();
     151                 :       8808 :     const char * p_end = p + s.size();
     152                 :            : 
     153                 :       8808 :     Xapian::Weight::Internal stat;
     154                 :            : 
     155                 :       8808 :     stat.total_length = decode_length(&p, p_end, false);
     156                 :       8808 :     stat.collection_size = decode_length(&p, p_end, false);
     157                 :       8808 :     stat.rset_size = decode_length(&p, p_end, false);
     158                 :            : 
     159                 :       8808 :     size_t n = decode_length(&p, p_end, false);
     160         [ +  + ]:      19908 :     while (n--) {
     161                 :      11100 :         size_t len = decode_length(&p, p_end, true);
     162                 :      11100 :         string term(p, len);
     163                 :      11100 :         p += len;
     164                 :      11100 :         Xapian::doccount termfreq(decode_length(&p, p_end, false));
     165         [ +  + ]:      11100 :         if (stat.rset_size == 0) {
     166                 :      10866 :             stat.termfreqs.insert(make_pair(term, TermFreqs(termfreq, 0)));
     167                 :            :         } else {
     168                 :        234 :             Xapian::doccount reltermfreq(decode_length(&p, p_end, false));
     169                 :            :             stat.termfreqs.insert(make_pair(term,
     170                 :        234 :                                             TermFreqs(termfreq, reltermfreq)));
     171                 :            :         }
     172                 :            :     }
     173                 :            : 
     174                 :          0 :     return stat;
     175                 :            : }
     176                 :            : 
     177                 :            : string
     178                 :       4404 : serialise_mset(const Xapian::MSet &mset)
     179                 :            : {
     180                 :       4404 :     string result;
     181                 :            : 
     182                 :       4404 :     result += encode_length(mset.get_firstitem());
     183                 :       4404 :     result += encode_length(mset.get_matches_lower_bound());
     184                 :       4404 :     result += encode_length(mset.get_matches_estimated());
     185                 :       4404 :     result += encode_length(mset.get_matches_upper_bound());
     186                 :       4404 :     result += encode_length(mset.get_uncollapsed_matches_lower_bound());
     187                 :       4404 :     result += encode_length(mset.get_uncollapsed_matches_estimated());
     188                 :       4404 :     result += encode_length(mset.get_uncollapsed_matches_upper_bound());
     189                 :       4404 :     result += serialise_double(mset.get_max_possible());
     190                 :       4404 :     result += serialise_double(mset.get_max_attained());
     191                 :            : 
     192                 :       4404 :     result += serialise_double(mset.internal->percent_factor);
     193                 :            : 
     194                 :       4404 :     result += encode_length(mset.size());
     195         [ +  + ]:      43068 :     for (Xapian::MSetIterator i = mset.begin(); i != mset.end(); ++i) {
     196                 :      38664 :         result += serialise_double(i.get_weight());
     197                 :      38664 :         result += encode_length(*i);
     198                 :      38664 :         result += encode_length(i.get_collapse_key().size());
     199                 :      38664 :         result += i.get_collapse_key();
     200                 :      38664 :         result += encode_length(i.get_collapse_count());
     201                 :       4404 :     }
     202                 :            : 
     203                 :            :     const map<string, Xapian::MSet::Internal::TermFreqAndWeight> &termfreqandwts
     204                 :       4404 :         = mset.internal->termfreqandwts;
     205                 :            : 
     206                 :       4404 :     map<string, Xapian::MSet::Internal::TermFreqAndWeight>::const_iterator j;
     207         [ +  + ]:       9972 :     for (j = termfreqandwts.begin(); j != termfreqandwts.end(); ++j) {
     208                 :       5568 :         result += encode_length(j->first.size());
     209                 :       5568 :         result += j->first;
     210                 :       5568 :         result += encode_length(j->second.termfreq);
     211                 :       5568 :         result += serialise_double(j->second.termweight);
     212                 :            :     }
     213                 :            : 
     214                 :          0 :     return result;
     215                 :            : }
     216                 :            : 
     217                 :            : Xapian::MSet
     218                 :       4404 : unserialise_mset(const char * p, const char * p_end)
     219                 :            : {
     220                 :       4404 :     Xapian::doccount firstitem = decode_length(&p, p_end, false);
     221                 :       4404 :     Xapian::doccount matches_lower_bound = decode_length(&p, p_end, false);
     222                 :       4404 :     Xapian::doccount matches_estimated = decode_length(&p, p_end, false);
     223                 :       4404 :     Xapian::doccount matches_upper_bound = decode_length(&p, p_end, false);
     224                 :       4404 :     Xapian::doccount uncollapsed_lower_bound = decode_length(&p, p_end, false);
     225                 :       4404 :     Xapian::doccount uncollapsed_estimated = decode_length(&p, p_end, false);
     226                 :       4404 :     Xapian::doccount uncollapsed_upper_bound = decode_length(&p, p_end, false);
     227                 :       4404 :     Xapian::weight max_possible = unserialise_double(&p, p_end);
     228                 :       4404 :     Xapian::weight max_attained = unserialise_double(&p, p_end);
     229                 :            : 
     230                 :       4404 :     double percent_factor = unserialise_double(&p, p_end);
     231                 :            : 
     232                 :       4404 :     vector<Xapian::Internal::MSetItem> items;
     233                 :       4404 :     size_t msize = decode_length(&p, p_end, false);
     234         [ +  + ]:      43068 :     while (msize-- > 0) {
     235                 :      38664 :         Xapian::weight wt = unserialise_double(&p, p_end);
     236                 :      38664 :         Xapian::docid did = decode_length(&p, p_end, false);
     237                 :      38664 :         size_t len = decode_length(&p, p_end, true);
     238                 :      38664 :         string key(p, len);
     239                 :      38664 :         p += len;
     240                 :      38664 :         Xapian::doccount collapse_cnt = decode_length(&p, p_end, false);
     241                 :      38664 :         items.push_back(Xapian::Internal::MSetItem(wt, did, key, collapse_cnt));
     242                 :            :     }
     243                 :            : 
     244                 :       4404 :     map<string, Xapian::MSet::Internal::TermFreqAndWeight> terminfo;
     245         [ +  + ]:       9972 :     while (p != p_end) {
     246                 :       5568 :         Xapian::MSet::Internal::TermFreqAndWeight tfaw;
     247                 :       5568 :         size_t len = decode_length(&p, p_end, true);
     248                 :       5568 :         string term(p, len);
     249                 :       5568 :         p += len;
     250                 :       5568 :         tfaw.termfreq = decode_length(&p, p_end, false);
     251                 :       5568 :         tfaw.termweight = unserialise_double(&p, p_end);
     252                 :       5568 :         terminfo.insert(make_pair(term, tfaw));
     253                 :            :     }
     254                 :            : 
     255                 :            :     return Xapian::MSet(new Xapian::MSet::Internal(
     256                 :            :                                        firstitem,
     257                 :            :                                        matches_upper_bound,
     258                 :            :                                        matches_lower_bound,
     259                 :            :                                        matches_estimated,
     260                 :            :                                        uncollapsed_upper_bound,
     261                 :            :                                        uncollapsed_lower_bound,
     262                 :            :                                        uncollapsed_estimated,
     263                 :            :                                        max_possible, max_attained,
     264                 :       4404 :                                        items, terminfo, percent_factor));
     265                 :            : }
     266                 :            : 
     267                 :            : string
     268                 :       4410 : serialise_rset(const Xapian::RSet &rset)
     269                 :            : {
     270                 :       4410 :     const set<Xapian::docid> & items = rset.internal->get_items();
     271                 :       4410 :     string result;
     272                 :       4410 :     set<Xapian::docid>::const_iterator i;
     273                 :       4410 :     Xapian::docid lastdid = 0;
     274         [ +  + ]:       4470 :     for (i = items.begin(); i != items.end(); ++i) {
     275                 :         60 :         Xapian::docid did = *i;
     276                 :         60 :         result += encode_length(did - lastdid - 1);
     277                 :         60 :         lastdid = did;
     278                 :            :     }
     279                 :          0 :     return result;
     280                 :            : }
     281                 :            : 
     282                 :            : Xapian::RSet
     283                 :       4404 : unserialise_rset(const string &s)
     284                 :            : {
     285                 :       4404 :     Xapian::RSet rset;
     286                 :            : 
     287                 :       4404 :     const char * p = s.data();
     288                 :       4404 :     const char * p_end = p + s.size();
     289                 :            : 
     290                 :       4404 :     Xapian::docid did = 0;
     291         [ +  + ]:       4464 :     while (p != p_end) {
     292                 :         60 :         did += decode_length(&p, p_end, false) + 1;
     293                 :         60 :         rset.add_document(did);
     294                 :            :     }
     295                 :            : 
     296                 :          0 :     return rset;
     297                 :            : }
     298                 :            : 
     299                 :            : string
     300                 :      98191 : serialise_document(const Xapian::Document &doc)
     301                 :            : {
     302                 :      98191 :     string result;
     303                 :            : 
     304                 :      98191 :     size_t n = doc.values_count();
     305                 :      98191 :     result += encode_length(n);
     306                 :      98191 :     Xapian::ValueIterator value;
     307         [ +  + ]:     485324 :     for (value = doc.values_begin(); value != doc.values_end(); ++value) {
     308                 :     387133 :         result += encode_length(value.get_valueno());
     309                 :     387133 :         result += encode_length((*value).size());
     310                 :     387133 :         result += *value;
     311                 :     387133 :         --n;
     312                 :            :     }
     313                 :            :     Assert(n == 0);
     314                 :            : 
     315                 :      98191 :     n = doc.termlist_count();
     316                 :      98191 :     result += encode_length(n);
     317                 :      98191 :     Xapian::TermIterator term;
     318         [ +  + ]:    1406600 :     for (term = doc.termlist_begin(); term != doc.termlist_end(); ++term) {
     319                 :    1308409 :         result += encode_length((*term).size());
     320                 :    1308409 :         result += *term;
     321                 :    1308409 :         result += encode_length(term.get_wdf());
     322                 :            : 
     323                 :    1308409 :         size_t x = term.positionlist_count();
     324                 :    1308409 :         result += encode_length(x);
     325                 :    1308409 :         Xapian::PositionIterator pos;
     326                 :    1308409 :         Xapian::termpos oldpos = 0;
     327         [ +  + ]:    2641200 :         for (pos = term.positionlist_begin(); pos != term.positionlist_end(); ++pos) {
     328                 :    1332791 :             Xapian::termpos diff = *pos - oldpos;
     329                 :    1332791 :             string delta = encode_length(diff);
     330                 :    1332791 :             result += delta;
     331                 :    1332791 :             oldpos = *pos;
     332                 :    1332791 :             --x;
     333                 :            :         }
     334                 :            :         Assert(x == 0);
     335                 :    1308409 :         --n;
     336                 :            :     }
     337                 :            :     Assert(n == 0);
     338                 :            : 
     339                 :      98191 :     result += doc.get_data();
     340                 :      98191 :     return result;
     341                 :            : }
     342                 :            : 
     343                 :            : Xapian::Document
     344                 :      98189 : unserialise_document(const string &s)
     345                 :            : {
     346                 :      98189 :     Xapian::Document doc;
     347                 :      98189 :     const char * p = s.data();
     348                 :      98189 :     const char * p_end = p + s.size();
     349                 :            : 
     350                 :      98189 :     size_t n_values = decode_length(&p, p_end, false);
     351         [ +  + ]:     485321 :     while (n_values--) {
     352                 :     387132 :         Xapian::valueno valno = decode_length(&p, p_end, false);
     353                 :     387132 :         size_t len = decode_length(&p, p_end, true);
     354                 :     387132 :         doc.add_value(valno, string(p, len));
     355                 :     387132 :         p += len;
     356                 :            :     }
     357                 :            : 
     358                 :      98189 :     size_t n_terms = decode_length(&p, p_end, false);
     359         [ +  + ]:    1406597 :     while (n_terms--) {
     360                 :    1308408 :         size_t len = decode_length(&p, p_end, true);
     361                 :    1308408 :         string term(p, len);
     362                 :    1308408 :         p += len;
     363                 :            : 
     364                 :            :         // Set all the wdf using add_term, then pass wdf_inc 0 to add_posting.
     365                 :    1308408 :         Xapian::termcount wdf = decode_length(&p, p_end, false);
     366                 :    1308408 :         doc.add_term(term, wdf);
     367                 :            : 
     368                 :    1308408 :         size_t n_pos = decode_length(&p, p_end, false);
     369                 :    1308408 :         Xapian::termpos pos = 0;
     370         [ +  + ]:    2641199 :         while (n_pos--) {
     371                 :    1332791 :             pos += decode_length(&p, p_end, false);
     372                 :    1332791 :             doc.add_posting(term, pos, 0);
     373                 :            :         }
     374                 :            :     }
     375                 :            : 
     376                 :      98189 :     doc.set_data(string(p, p_end - p));
     377                 :          0 :     return doc;
     378                 :            : }

Generated by: LCOV version 1.8