LCOV - code coverage report
Current view: top level - backends/glass - glass_positionlist.cc (source / functions) Hit Total Coverage
Test: Test Coverage for xapian-core 7028d852e609 Lines: 84 94 89.4 %
Date: 2019-02-17 14:59:59 Functions: 11 13 84.6 %
Branches: 56 98 57.1 %

           Branch data     Line data    Source code
       1                 :            : /** @file glass_positionlist.cc
       2                 :            :  * @brief A position list in a glass database.
       3                 :            :  */
       4                 :            : /* Copyright (C) 2004,2005,2006,2008,2009,2010,2013,2017,2019 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
      19                 :            :  * USA
      20                 :            :  */
      21                 :            : 
      22                 :            : #include <config.h>
      23                 :            : 
      24                 :            : #include "glass_positionlist.h"
      25                 :            : 
      26                 :            : #include <xapian/types.h>
      27                 :            : 
      28                 :            : #include "bitstream.h"
      29                 :            : #include "debuglog.h"
      30                 :            : #include "pack.h"
      31                 :            : 
      32                 :            : #include <string>
      33                 :            : 
      34                 :            : using namespace std;
      35                 :            : 
      36                 :            : void
      37                 :    1772238 : GlassPositionListTable::pack(string & s,
      38                 :            :                              const Xapian::VecCOW<Xapian::termpos> & vec) const
      39                 :            : {
      40                 :            :     LOGCALL_VOID(DB, "GlassPositionListTable::pack", s | vec);
      41                 :            :     Assert(!vec.empty());
      42                 :            : 
      43                 :    1772238 :     pack_uint(s, vec.back());
      44                 :            : 
      45         [ +  + ]:    1772238 :     if (vec.size() > 1) {
      46         [ +  - ]:     186673 :         BitWriter wr(s);
      47 [ +  - ][ +  - ]:     186673 :         wr.encode(vec[0], vec.back());
                 [ +  - ]
      48 [ +  - ][ +  - ]:     186673 :         wr.encode(vec.size() - 2, vec.back() - vec[0]);
                 [ +  - ]
      49         [ +  - ]:     186673 :         wr.encode_interpolative(vec, 0, vec.size() - 1);
      50 [ +  - ][ +  - ]:     186673 :         swap(s, wr.freeze());
      51                 :            :     }
      52                 :    1772238 : }
      53                 :            : 
      54                 :            : Xapian::termcount
      55                 :       4114 : GlassPositionListTable::positionlist_count(const string& data) const
      56                 :            : {
      57                 :            :     LOGCALL(DB, Xapian::termcount, "GlassPositionListTable::positionlist_count", data);
      58                 :            : 
      59                 :            :     Assert(!data.empty());
      60                 :            : 
      61                 :       4114 :     const char * pos = data.data();
      62                 :       4114 :     const char * end = pos + data.size();
      63                 :            :     Xapian::termpos pos_last;
      64         [ -  + ]:       4114 :     if (!unpack_uint(&pos, end, &pos_last)) {
      65 [ #  # ][ #  # ]:          0 :         throw Xapian::DatabaseCorruptError("Position list data corrupt");
                 [ #  # ]
      66                 :            :     }
      67         [ +  + ]:       4114 :     if (pos == end) {
      68                 :            :         // Special case for single entry position list.
      69                 :       3541 :         RETURN(1);
      70                 :            :     }
      71                 :            : 
      72                 :            :     // Skip the header we just read.
      73                 :        573 :     BitReader rd(pos, end);
      74         [ +  - ]:        573 :     Xapian::termpos pos_first = rd.decode(pos_last);
      75         [ +  - ]:        573 :     Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
      76                 :       4114 :     RETURN(pos_size);
      77                 :            : }
      78                 :            : 
      79                 :            : Xapian::termcount
      80                 :      24315 : GlassPositionListTable::positionlist_count(Xapian::docid did,
      81                 :            :                                            const string & term) const
      82                 :            : {
      83                 :            :     LOGCALL(DB, Xapian::termcount, "GlassPositionListTable::positionlist_count", did | term);
      84                 :            : 
      85         [ +  - ]:      24315 :     string data;
      86 [ +  - ][ +  - ]:      24315 :     if (!get_exact_entry(make_key(did, term), data)) {
                 [ +  + ]
      87                 :      20221 :         RETURN(0);
      88                 :            :     }
      89                 :            : 
      90         [ +  - ]:      24315 :     RETURN(positionlist_count(data));
      91                 :            : }
      92                 :            : 
      93                 :            : ///////////////////////////////////////////////////////////////////////////
      94                 :            : 
      95                 :            : void
      96                 :      77365 : GlassBasePositionList::set_data(const string& data)
      97                 :            : {
      98                 :            :     LOGCALL_VOID(DB, "GlassBasePositionList::set_data", data);
      99                 :            : 
     100                 :      77365 :     have_started = false;
     101                 :            : 
     102         [ +  + ]:      77365 :     if (data.empty()) {
     103                 :            :         // There's no positional information for this term.
     104                 :      61643 :         size = 0;
     105                 :      61643 :         last = 0;
     106                 :      61643 :         current_pos = 1;
     107                 :      77365 :         return;
     108                 :            :     }
     109                 :            : 
     110                 :      15722 :     const char* pos = data.data();
     111                 :      15722 :     const char* end = pos + data.size();
     112                 :            :     Xapian::termpos pos_last;
     113         [ -  + ]:      15722 :     if (!unpack_uint(&pos, end, &pos_last)) {
     114 [ #  # ][ #  # ]:          0 :         throw Xapian::DatabaseCorruptError("Position list data corrupt");
                 [ #  # ]
     115                 :            :     }
     116                 :            : 
     117         [ +  + ]:      15722 :     if (pos == end) {
     118                 :            :         // Special case for single entry position list.
     119                 :      13479 :         size = 1;
     120                 :      13479 :         current_pos = last = pos_last;
     121                 :      13479 :         return;
     122                 :            :     }
     123                 :            : 
     124                 :       2243 :     rd.init(pos, end);
     125         [ +  - ]:       2243 :     Xapian::termpos pos_first = rd.decode(pos_last);
     126         [ +  - ]:       2243 :     Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
     127         [ +  - ]:       2243 :     rd.decode_interpolative(0, pos_size - 1, pos_first, pos_last);
     128                 :       2243 :     size = pos_size;
     129                 :       2243 :     last = pos_last;
     130                 :       2243 :     current_pos = pos_first;
     131                 :            : }
     132                 :            : 
     133                 :            : Xapian::termcount
     134                 :        546 : GlassBasePositionList::get_approx_size() const
     135                 :            : {
     136                 :            :     LOGCALL(DB, Xapian::termcount, "GlassBasePositionList::get_approx_size", NO_ARGS);
     137                 :        546 :     RETURN(size);
     138                 :            : }
     139                 :            : 
     140                 :            : Xapian::termpos
     141                 :          0 : GlassBasePositionList::back() const
     142                 :            : {
     143                 :            :     LOGCALL(DB, Xapian::termpos, "GlassBasePositionList::back", NO_ARGS);
     144                 :          0 :     RETURN(last);
     145                 :            : }
     146                 :            : 
     147                 :            : Xapian::termpos
     148                 :      56560 : GlassBasePositionList::get_position() const
     149                 :            : {
     150                 :            :     LOGCALL(DB, Xapian::termpos, "GlassBasePositionList::get_position", NO_ARGS);
     151                 :            :     Assert(have_started);
     152                 :      56560 :     RETURN(current_pos);
     153                 :            : }
     154                 :            : 
     155                 :            : bool
     156                 :     123246 : GlassBasePositionList::next()
     157                 :            : {
     158                 :            :     LOGCALL(DB, bool, "GlassBasePositionList::next", NO_ARGS);
     159         [ +  + ]:     123246 :     if (rare(!have_started)) {
     160                 :      75474 :         have_started = true;
     161                 :      75474 :         return current_pos <= last;
     162                 :            :     }
     163         [ +  + ]:      47772 :     if (current_pos == last) {
     164                 :      12522 :         return false;
     165                 :            :     }
     166                 :      35250 :     current_pos = rd.decode_interpolative_next();
     167                 :      35250 :     return true;
     168                 :            : }
     169                 :            : 
     170                 :            : bool
     171                 :       2224 : GlassBasePositionList::skip_to(Xapian::termpos termpos)
     172                 :            : {
     173                 :            :     LOGCALL(DB, bool, "GlassBasePositionList::skip_to", termpos);
     174                 :       2224 :     have_started = true;
     175         [ +  + ]:       2224 :     if (termpos >= last) {
     176         [ +  + ]:        891 :         if (termpos == last) {
     177                 :        261 :             current_pos = last;
     178                 :        261 :             return true;
     179                 :            :         }
     180                 :        630 :         return false;
     181                 :            :     }
     182         [ +  + ]:       1703 :     while (current_pos < termpos) {
     183         [ -  + ]:        370 :         if (current_pos == last) {
     184                 :          0 :             return false;
     185                 :            :         }
     186                 :        370 :         current_pos = rd.decode_interpolative_next();
     187                 :            :     }
     188                 :       1333 :     return true;
     189                 :            : }
     190                 :            : 
     191         [ +  - ]:       1572 : GlassPositionList::GlassPositionList(string&& data)
     192                 :            : {
     193                 :            :     LOGCALL_CTOR(DB, "GlassPositionList", data);
     194                 :            : 
     195         [ +  - ]:        786 :     pos_data = std::move(data);
     196                 :            : 
     197         [ +  - ]:        786 :     set_data(pos_data);
     198                 :        786 : }
     199                 :            : 
     200                 :      73390 : GlassPositionList::GlassPositionList(const GlassTable* table,
     201                 :            :                                      Xapian::docid did,
     202         [ +  - ]:      73393 :                                      const string& term)
     203                 :            : {
     204                 :            :     LOGCALL_CTOR(DB, "GlassPositionList", table | did | term);
     205                 :            : 
     206         [ +  + ]:      73387 :     if (!table->get_exact_entry(GlassPositionListTable::make_key(did, term),
     207 [ +  - ][ +  + ]:      73390 :                                 pos_data)) {
     208         [ +  - ]:      60967 :         pos_data.clear();
     209                 :            :     }
     210                 :            : 
     211         [ +  - ]:      73387 :     set_data(pos_data);
     212                 :      73387 : }
     213                 :            : 
     214                 :            : void
     215                 :          0 : GlassRePositionList::assign_data(string&& data)
     216                 :            : {
     217                 :            :     LOGCALL_VOID(DB, "GlassRePositionList::assign_data", data);
     218                 :            : 
     219                 :            :     // We need to ensure the data stays valid while in use, so abuse the cursor
     220                 :            :     // current_tag member as somewhere to store it.
     221                 :          0 :     cursor.to_end();
     222                 :          0 :     cursor.current_tag = std::move(data);
     223                 :            : 
     224                 :          0 :     set_data(cursor.current_tag);
     225                 :          0 : }
     226                 :            : 
     227                 :            : void
     228                 :       3192 : GlassRePositionList::read_data(Xapian::docid did,
     229                 :            :                                const string& term)
     230                 :            : {
     231                 :            :     LOGCALL_VOID(DB, "GlassRePositionList::read_data", did | term);
     232                 :            : 
     233 [ +  - ][ +  + ]:       3192 :     if (!cursor.find_exact(GlassPositionListTable::make_key(did, term))) {
     234                 :         12 :         cursor.current_tag.clear();
     235                 :            :     }
     236                 :            : 
     237                 :       3192 :     set_data(cursor.current_tag);
     238                 :       3192 : }

Generated by: LCOV version 1.11