LCOV - code coverage report
Current view: top level - api - keymaker.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core r Lines: 59 59 100.0 %
Date: 2011-08-21 Functions: 3 5 60.0 %
Branches: 51 56 91.1 %

           Branch data     Line data    Source code
       1                 :            : /** @file keymaker.cc
       2                 :            :  * @brief Build key strings for MSet ordering or collapsing.
       3                 :            :  */
       4                 :            : /* Copyright (C) 2007,2009 Olly Betts
       5                 :            :  *
       6                 :            :  * This program is free software; you can redistribute it and/or
       7                 :            :  * modify it under the terms of the GNU General Public License as
       8                 :            :  * published by the Free Software Foundation; either version 2 of the
       9                 :            :  * License, or (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/keymaker.h"
      24                 :            : 
      25                 :            : #include "xapian/document.h"
      26                 :            : 
      27                 :            : #include <string>
      28                 :            : #include <vector>
      29                 :            : 
      30                 :            : using namespace std;
      31                 :            : 
      32                 :            : namespace Xapian {
      33                 :            : 
      34 [ #  # ][ #  # ]:        141 : KeyMaker::~KeyMaker() { }
                 [ -  + ]
      35                 :            : 
      36                 :            : string
      37                 :        440 : MultiValueKeyMaker::operator()(const Xapian::Document & doc) const
      38                 :            : {
      39                 :        440 :     string result;
      40                 :            : 
      41                 :        440 :     vector<pair<Xapian::valueno, bool> >::const_iterator i = valnos.begin();
      42                 :            :     // Don't crash if valnos is empty.
      43         [ +  + ]:        440 :     if (rare(i == valnos.end())) return result;
      44                 :            : 
      45                 :        377 :     size_t last_not_empty_forwards = 0;
      46         [ +  + ]:        788 :     while (true) {
      47                 :            :         // All values (except for the last if it's sorted forwards) need to
      48                 :            :         // be adjusted.
      49                 :            :         //
      50                 :            :         // FIXME: allow Xapian::BAD_VALUENO to mean "relevance?"
      51                 :        788 :         string v = doc.get_value(i->first);
      52                 :        788 :         bool reverse_sort = i->second;
      53                 :            : 
      54   [ +  +  +  + ]:        788 :         if (reverse_sort || !v.empty())
                 [ +  + ]
      55                 :        650 :             last_not_empty_forwards = result.size();
      56                 :            : 
      57 [ +  + ][ +  + ]:        788 :         if (++i == valnos.end() && !reverse_sort) {
                 [ +  + ]
      58         [ +  + ]:        127 :             if (v.empty()) {
      59                 :            :                 // Trim off all the trailing empty forwards values.
      60                 :         43 :                 result.resize(last_not_empty_forwards);
      61                 :            :             } else {
      62                 :            :                 // No need to adjust the last value if it's sorted forwards.
      63                 :        127 :                 result += v;
      64                 :            :             }
      65                 :            :             break;
      66                 :            :         }
      67                 :            : 
      68         [ +  + ]:        661 :         if (reverse_sort) {
      69                 :            :             // For a reverse ordered value, we subtract each byte from '\xff',
      70                 :            :             // except for '\0' which we convert to "\xff\0".  We insert
      71                 :            :             // "\xff\xff" after the encoded value.
      72         [ +  + ]:        695 :             for (string::const_iterator j = v.begin(); j != v.end(); ++j) {
      73                 :        405 :                 unsigned char ch(*j);
      74                 :        405 :                 result += char(255 - ch);
      75         [ +  + ]:        405 :                 if (ch == 0) result += '\0';
      76                 :            :             }
      77                 :        290 :             result.append("\xff\xff", 2);
      78         [ +  + ]:        290 :             if (i == valnos.end()) break;
      79                 :         40 :             last_not_empty_forwards = result.size();
      80                 :            :         } else {
      81                 :            :             // For a forward ordered value (unless it's the last value), we
      82                 :            :             // convert any '\0' to "\0\xff".  We insert "\0\0" after the
      83                 :            :             // encoded value.
      84                 :        371 :             string::size_type j = 0, nul;
      85         [ +  + ]:        382 :             while ((nul = v.find('\0', j)) != string::npos) {
      86                 :         11 :                 ++nul;
      87                 :         11 :                 result.append(v, j, nul - j);
      88                 :         11 :                 result += '\xff';
      89                 :         11 :                 j = nul;
      90                 :            :             }
      91                 :        371 :             result.append(v, j, string::npos);
      92         [ +  + ]:        371 :             if (!v.empty())
      93                 :        276 :                 last_not_empty_forwards = result.size();
      94                 :        411 :             result.append("\0", 2);
      95                 :            :         }
      96                 :            :     }
      97                 :        440 :     return result;
      98                 :            : }
      99                 :            : 
     100                 :            : string
     101                 :        435 : MultiValueSorter::operator()(const Xapian::Document & doc) const
     102                 :            : {
     103                 :        435 :     string result;
     104                 :            : 
     105                 :        435 :     vector<pair<Xapian::valueno, bool> >::const_iterator i = valnos.begin();
     106                 :            :     // Don't crash if valnos is empty.
     107         [ +  + ]:        435 :     if (rare(i == valnos.end())) return result;
     108                 :            : 
     109         [ +  + ]:        767 :     while (true) {
     110                 :            :         // All values (except for the last if it's sorted forwards) need to
     111                 :            :         // be adjusted.
     112                 :            :         //
     113                 :            :         // FIXME: allow Xapian::BAD_VALUENO to mean "relevance?"
     114                 :        767 :         string v = doc.get_value(i->first);
     115                 :        767 :         bool reverse_sort = !i->second;
     116                 :            : 
     117   [ +  +  +  + ]:        767 :         if (++i == valnos.end() && !reverse_sort) {
                 [ +  + ]
     118                 :            :             // No need to adjust the last value if it's sorted forwards.
     119                 :        123 :             result += v;
     120                 :            :             break;
     121                 :            :         }
     122                 :            : 
     123         [ +  + ]:        644 :         if (reverse_sort) {
     124                 :            :             // For a reverse ordered value, we subtract each byte from '\xff',
     125                 :            :             // except for '\0' which we convert to "\xff\0".  We insert
     126                 :            :             // "\xff\xff" after the encoded value.
     127         [ +  + ]:        694 :             for (string::const_iterator j = v.begin(); j != v.end(); ++j) {
     128                 :        405 :                 unsigned char ch(*j);
     129                 :        405 :                 result += char(255 - ch);
     130         [ +  + ]:        405 :                 if (ch == 0) result += '\0';
     131                 :            :             }
     132                 :        289 :             result.append("\xff\xff", 2);
     133         [ +  + ]:        289 :             if (i == valnos.end()) break;
     134                 :            :         } else {
     135                 :            :             // For a forward ordered value (unless it's the last value), we
     136                 :            :             // convert any '\0' to "\0\xff".  We insert "\0\0" after the
     137                 :            :             // encoded value.
     138                 :        355 :             string::size_type j = 0, nul;
     139         [ +  + ]:        363 :             while ((nul = v.find('\0', j)) != string::npos) {
     140                 :          8 :                 ++nul;
     141                 :          8 :                 result.append(v, j, nul - j);
     142                 :          8 :                 result += '\xff';
     143                 :          8 :                 j = nul;
     144                 :            :             }
     145                 :        355 :             result.append(v, j, string::npos);
     146                 :        395 :             result.append("\0", 2);
     147                 :            :         }
     148                 :            :     }
     149                 :        435 :     return result;
     150                 :            : }
     151                 :            : 
     152                 :            : }

Generated by: LCOV version 1.8