Remove some superfluous blank lines
[xapian.git] / xapian-core / backends / glass / glass_termlist.cc
blobd43694c44c5d38b4f6a873b5f5e9a541d5822b14
1 /* glass_termlist.cc: Termlists in a glass database
3 * Copyright 1999,2000,2001 BrightStation PLC
4 * Copyright 2002 Ananova Ltd
5 * Copyright 2002,2003,2004,2006,2007,2008,2009,2010,2014 Olly Betts
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
20 * USA
23 #include <config.h>
24 #include "glass_termlist.h"
26 #include "xapian/error.h"
28 #include "expand/expandweight.h"
29 #include "glass_positionlist.h"
30 #include "debuglog.h"
31 #include "omassert.h"
32 #include "pack.h"
33 #include "str.h"
35 using namespace std;
36 using Xapian::Internal::intrusive_ptr;
38 GlassTermList::GlassTermList(intrusive_ptr<const GlassDatabase> db_,
39 Xapian::docid did_)
40 : db(db_), did(did_), current_wdf(0), current_termfreq(0)
42 LOGCALL_CTOR(DB, "GlassTermList", db_ | did_);
44 if (!db->termlist_table.get_exact_entry(GlassTermListTable::make_key(did),
45 data))
46 throw Xapian::DocNotFoundError("No termlist for document " + str(did));
48 pos = data.data();
49 end = pos + data.size();
51 if (pos == end) {
52 doclen = 0;
53 termlist_size = 0;
54 return;
57 // Read doclen
58 if (!unpack_uint(&pos, end, &doclen)) {
59 const char *msg;
60 if (pos == 0) {
61 msg = "Too little data for doclen in termlist";
62 } else {
63 msg = "Overflowed value for doclen in termlist";
65 throw Xapian::DatabaseCorruptError(msg);
68 // Read termlist_size
69 if (!unpack_uint(&pos, end, &termlist_size)) {
70 const char *msg;
71 if (pos == 0) {
72 msg = "Too little data for list size in termlist";
73 } else {
74 msg = "Overflowed value for list size in termlist";
76 throw Xapian::DatabaseCorruptError(msg);
80 Xapian::termcount
81 GlassTermList::get_doclength() const
83 LOGCALL(DB, Xapian::termcount, "GlassTermList::get_doclength", NO_ARGS);
84 RETURN(doclen);
87 Xapian::termcount
88 GlassTermList::get_unique_terms() const
90 LOGCALL(DB, Xapian::termcount, "GlassTermList::get_unique_terms", NO_ARGS);
91 // get_unique_terms() really ought to only count terms with wdf > 0, but
92 // that's expensive to calculate on demand, so for now let's just ensure
93 // unique_terms <= doclen.
94 RETURN(min(termlist_size, doclen));
97 Xapian::termcount
98 GlassTermList::get_approx_size() const
100 LOGCALL(DB, Xapian::termcount, "GlassTermList::get_approx_size", NO_ARGS);
101 RETURN(termlist_size);
104 void
105 GlassTermList::accumulate_stats(Xapian::Internal::ExpandStats & stats) const
107 LOGCALL_VOID(DB, "GlassTermList::accumulate_stats", stats);
108 Assert(!at_end());
109 stats.accumulate(current_wdf, doclen, get_termfreq(), db->get_doccount());
112 string
113 GlassTermList::get_termname() const
115 LOGCALL(DB, string, "GlassTermList::get_termname", NO_ARGS);
116 RETURN(current_term);
119 Xapian::termcount
120 GlassTermList::get_wdf() const
122 LOGCALL(DB, Xapian::termcount, "GlassTermList::get_wdf", NO_ARGS);
123 RETURN(current_wdf);
126 Xapian::doccount
127 GlassTermList::get_termfreq() const
129 LOGCALL(DB, Xapian::doccount, "GlassTermList::get_termfreq", NO_ARGS);
130 if (current_termfreq == 0)
131 db->get_freqs(current_term, &current_termfreq, NULL);
132 RETURN(current_termfreq);
135 TermList *
136 GlassTermList::next()
138 LOGCALL(DB, TermList *, "GlassTermList::next", NO_ARGS);
139 Assert(!at_end());
140 if (pos == end) {
141 pos = NULL;
142 RETURN(NULL);
145 // Reset to 0 to indicate that the termfreq needs to be read.
146 current_termfreq = 0;
148 bool wdf_in_reuse = false;
149 if (!current_term.empty()) {
150 // Find out how much of the previous term to reuse.
151 size_t len = static_cast<unsigned char>(*pos++);
152 if (len > current_term.size()) {
153 // The wdf is also stored in the "reuse" byte.
154 wdf_in_reuse = true;
155 size_t divisor = current_term.size() + 1;
156 current_wdf = len / divisor - 1;
157 len %= divisor;
159 current_term.resize(len);
162 // Append the new tail to form the next term.
163 size_t append_len = static_cast<unsigned char>(*pos++);
164 current_term.append(pos, append_len);
165 pos += append_len;
167 // Read the wdf if it wasn't packed into the reuse byte.
168 if (!wdf_in_reuse && !unpack_uint(&pos, end, &current_wdf)) {
169 const char *msg;
170 if (pos == 0) {
171 msg = "Too little data for wdf in termlist";
172 } else {
173 msg = "Overflowed value for wdf in termlist";
175 throw Xapian::DatabaseCorruptError(msg);
178 RETURN(NULL);
181 TermList *
182 GlassTermList::skip_to(const string & term)
184 LOGCALL(API, TermList *, "GlassTermList::skip_to", term);
185 while (pos != NULL && current_term < term) {
186 (void)GlassTermList::next();
188 RETURN(NULL);
191 bool
192 GlassTermList::at_end() const
194 LOGCALL(DB, bool, "GlassTermList::at_end", NO_ARGS);
195 RETURN(pos == NULL);
198 Xapian::termcount
199 GlassTermList::positionlist_count() const
201 LOGCALL(DB, Xapian::termcount, "GlassTermList::positionlist_count", NO_ARGS);
202 RETURN(db->position_table.positionlist_count(did, current_term));
205 PositionList*
206 GlassTermList::positionlist_begin() const
208 LOGCALL(DB, PositionList*, "GlassTermList::positionlist_begin", NO_ARGS);
209 RETURN(new GlassPositionList(&db->position_table, did, current_term));
212 #ifdef DISABLE_GPL_LIBXAPIAN
213 # error GPL source we cannot relicense included in libxapian
214 #endif