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
24 #include "glass_termlist.h"
26 #include "xapian/error.h"
28 #include "expand/expandweight.h"
29 #include "glass_positionlist.h"
36 using Xapian::Internal::intrusive_ptr
;
38 GlassTermList::GlassTermList(intrusive_ptr
<const GlassDatabase
> db_
,
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
),
46 throw Xapian::DocNotFoundError("No termlist for document " + str(did
));
49 end
= pos
+ data
.size();
58 if (!unpack_uint(&pos
, end
, &doclen
)) {
61 msg
= "Too little data for doclen in termlist";
63 msg
= "Overflowed value for doclen in termlist";
65 throw Xapian::DatabaseCorruptError(msg
);
69 if (!unpack_uint(&pos
, end
, &termlist_size
)) {
72 msg
= "Too little data for list size in termlist";
74 msg
= "Overflowed value for list size in termlist";
76 throw Xapian::DatabaseCorruptError(msg
);
81 GlassTermList::get_doclength() const
83 LOGCALL(DB
, Xapian::termcount
, "GlassTermList::get_doclength", NO_ARGS
);
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
));
98 GlassTermList::get_approx_size() const
100 LOGCALL(DB
, Xapian::termcount
, "GlassTermList::get_approx_size", NO_ARGS
);
101 RETURN(termlist_size
);
105 GlassTermList::accumulate_stats(Xapian::Internal::ExpandStats
& stats
) const
107 LOGCALL_VOID(DB
, "GlassTermList::accumulate_stats", stats
);
109 stats
.accumulate(current_wdf
, doclen
, get_termfreq(), db
->get_doccount());
113 GlassTermList::get_termname() const
115 LOGCALL(DB
, string
, "GlassTermList::get_termname", NO_ARGS
);
116 RETURN(current_term
);
120 GlassTermList::get_wdf() const
122 LOGCALL(DB
, Xapian::termcount
, "GlassTermList::get_wdf", NO_ARGS
);
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
, ¤t_termfreq
, NULL
);
132 RETURN(current_termfreq
);
136 GlassTermList::next()
138 LOGCALL(DB
, TermList
*, "GlassTermList::next", NO_ARGS
);
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.
155 size_t divisor
= current_term
.size() + 1;
156 current_wdf
= len
/ divisor
- 1;
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
);
167 // Read the wdf if it wasn't packed into the reuse byte.
168 if (!wdf_in_reuse
&& !unpack_uint(&pos
, end
, ¤t_wdf
)) {
171 msg
= "Too little data for wdf in termlist";
173 msg
= "Overflowed value for wdf in termlist";
175 throw Xapian::DatabaseCorruptError(msg
);
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();
192 GlassTermList::at_end() const
194 LOGCALL(DB
, bool, "GlassTermList::at_end", NO_ARGS
);
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
));
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