xapian-core  1.4.26
glass_positionlist.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2004,2005,2006,2008,2009,2010,2013,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 #include <vector>
34 
35 using namespace std;
36 
37 void
39  const vector<Xapian::termpos> & vec) const
40 {
41  LOGCALL_VOID(DB, "GlassPositionListTable::pack", s | vec);
42  Assert(!vec.empty());
43 
44  pack_uint(s, vec.back());
45 
46  if (vec.size() > 1) {
47  BitWriter wr(s);
48  wr.encode(vec[0], vec.back());
49  wr.encode(vec.size() - 2, vec.back() - vec[0]);
50  wr.encode_interpolative(vec, 0, vec.size() - 1);
51  swap(s, wr.freeze());
52  }
53 }
54 
57 {
58  LOGCALL(DB, Xapian::termcount, "GlassPositionListTable::positionlist_count", data);
59 
60  Assert(!data.empty());
61 
62  const char * pos = data.data();
63  const char * end = pos + data.size();
64  Xapian::termpos pos_last;
65  if (!unpack_uint(&pos, end, &pos_last)) {
66  throw Xapian::DatabaseCorruptError("Position list data corrupt");
67  }
68  if (pos == end) {
69  // Special case for single entry position list.
70  RETURN(1);
71  }
72 
73  // Skip the header we just read.
74  BitReader rd(data, pos - data.data());
75  Xapian::termpos pos_first = rd.decode(pos_last);
76  Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
77  RETURN(pos_size);
78 }
79 
82  const string & term) const
83 {
84  LOGCALL(DB, Xapian::termcount, "GlassPositionListTable::positionlist_count", did | term);
85 
86  string data;
87  if (!get_exact_entry(make_key(did, term), data)) {
88  RETURN(0);
89  }
90 
91  RETURN(positionlist_count(data));
92 }
93 
95 
96 bool
97 GlassPositionList::read_data(const string & data)
98 {
99  LOGCALL(DB, bool, "GlassPositionList::read_data", data);
100 
101  have_started = false;
102 
103  if (data.empty()) {
104  // There's no positional information for this term.
105  size = 0;
106  last = 0;
107  current_pos = 1;
108  RETURN(false);
109  }
110 
111  const char * pos = data.data();
112  const char * end = pos + data.size();
113  Xapian::termpos pos_last;
114  if (!unpack_uint(&pos, end, &pos_last)) {
115  throw Xapian::DatabaseCorruptError("Position list data corrupt");
116  }
117  if (pos == end) {
118  // Special case for single entry position list.
119  size = 1;
120  current_pos = last = pos_last;
121  RETURN(true);
122  }
123  // Skip the header we just read.
124  rd.init(data, pos - data.data());
125  Xapian::termpos pos_first = rd.decode(pos_last);
126  Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
127  rd.decode_interpolative(0, pos_size - 1, pos_first, pos_last);
128  size = pos_size;
129  last = pos_last;
130  current_pos = pos_first;
131  RETURN(true);
132 }
133 
134 bool
136  const string & tname)
137 {
138  LOGCALL(DB, bool, "GlassPositionList::read_data", table | did | tname);
139  if (!cursor.get()) {
140  cursor.reset(table->cursor_get());
141  }
142  if (cursor.get() &&
143  cursor->find_exact(GlassPositionListTable::make_key(did, tname))) {
144  RETURN(read_data(cursor->current_tag));
145  }
146  RETURN(read_data(string()));
147 }
148 
151 {
152  LOGCALL(DB, Xapian::termcount, "GlassPositionList::get_approx_size", NO_ARGS);
153  RETURN(size);
154 }
155 
158 {
159  LOGCALL(DB, Xapian::termpos, "GlassPositionList::get_position", NO_ARGS);
160  Assert(have_started);
161  RETURN(current_pos);
162 }
163 
164 bool
166 {
167  LOGCALL(DB, bool, "GlassPositionList::next", NO_ARGS);
168  if (rare(!have_started)) {
169  have_started = true;
170  return current_pos <= last;
171  }
172  if (current_pos == last) {
173  return false;
174  }
175  current_pos = rd.decode_interpolative_next();
176  return true;
177 }
178 
179 bool
181 {
182  LOGCALL(DB, bool, "GlassPositionList::skip_to", termpos);
183  have_started = true;
184  if (termpos >= last) {
185  if (termpos == last) {
186  current_pos = last;
187  return true;
188  }
189  return false;
190  }
191  while (current_pos < termpos) {
192  if (current_pos == last) {
193  return false;
194  }
195  current_pos = rd.decode_interpolative_next();
196  }
197  return true;
198 }
void pack(string &s, const std::vector< Xapian::termpos > &vec) const
Pack a position list into a string.
#define RETURN(A)
Definition: debuglog.h:493
#define Assert(COND)
Definition: omassert.h:122
bool next()
Advance to the next term position in the list.
Xapian::termcount positionlist_count(const string &data) const
Return the number of entries in specified position list data.
typedefs for Xapian
A position list in a glass database.
Class managing a Btree table in a Glass database.
Definition: glass_table.h:425
Xapian::termcount get_approx_size() const
Returns size of position list.
#define LOGCALL_VOID(CATEGORY, FUNC, PARAMS)
Definition: debuglog.h:488
STL namespace.
bool read_data(const string &data)
Fill list with data, and move the position to the start.
#define rare(COND)
Definition: config.h:575
void encode_interpolative(const std::vector< Xapian::termpos > &pos, int j, int k)
Perform interpolative encoding of pos elements between j and k.
Definition: bitstream.cc:157
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:72
Read a stream created by BitWriter.
Definition: bitstream.h:64
bool skip_to(Xapian::termpos termpos)
Advance to the first term position which is at least termpos.
Classes to encode/decode a bitstream.
Xapian::termpos decode(Xapian::termpos outof, bool force=false)
Definition: bitstream.cc:176
DatabaseCorruptError indicates database corruption was detected.
Definition: error.h:409
void pack_uint(std::string &s, U value)
Append an encoded unsigned integer to a string.
Definition: pack.h:382
Xapian::termpos get_position() const
Returns current position.
GlassCursor * cursor_get() const
Get a cursor for reading from the table.
Pack types into strings and unpack them again.
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:83
bool unpack_uint(const char **p, const char *end, U *result)
Decode an unsigned integer from a string.
Definition: pack.h:413
Create a stream to which non-byte-aligned values can be written.
Definition: bitstream.h:33
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:52
void encode(Xapian::termpos value, Xapian::termpos outof)
Encode value, known to be less than outof.
Definition: bitstream.cc:95
static string make_key(Xapian::docid did, const string &term)
string make_key(Xapian::docid did)
Definition: chert_record.cc:35
Debug logging macros.
#define LOGCALL(CATEGORY, TYPE, FUNC, PARAMS)
Definition: debuglog.h:487
std::string & freeze()
Finish encoding and return the encoded data as a std::string.
Definition: bitstream.h:50