00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include "flint_positionlist.h"
00024
00025 #include <xapian/types.h>
00026
00027 #include "bitstream.h"
00028 #include "debuglog.h"
00029 #include "flint_utils.h"
00030
00031 #include <string>
00032 #include <vector>
00033
00034 using namespace std;
00035
00036 void
00037 FlintPositionListTable::set_positionlist(Xapian::docid did,
00038 const string & tname,
00039 Xapian::PositionIterator pos,
00040 const Xapian::PositionIterator &pos_end,
00041 bool check_for_update)
00042 {
00043 LOGCALL_VOID(DB, "FlintPositionList::set_positionlist", did | tname | pos | pos_end | check_for_update);
00044 Assert(pos != pos_end);
00045
00046
00047 vector<Xapian::termpos> poscopy(pos, pos_end);
00048
00049 string key = make_key(did, tname);
00050
00051 string s = F_pack_uint(poscopy.back());
00052
00053 if (poscopy.size() > 1) {
00054 BitWriter wr(s);
00055 wr.encode(poscopy[0], poscopy.back());
00056 wr.encode(poscopy.size() - 2, poscopy.back() - poscopy[0]);
00057 wr.encode_interpolative(poscopy, 0, poscopy.size() - 1);
00058 swap(s, wr.freeze());
00059 }
00060
00061 if (check_for_update) {
00062 string old_tag;
00063 if (get_exact_entry(key, old_tag) && s == old_tag)
00064 return;
00065 }
00066 add(key, s);
00067 }
00068
00069 Xapian::termcount
00070 FlintPositionListTable::positionlist_count(Xapian::docid did,
00071 const string & term) const
00072 {
00073 LOGCALL_VOID(DB, "FlintPositionListTable::positionlist_count", did | term);
00074
00075 string data;
00076 if (!get_exact_entry(F_pack_uint_preserving_sort(did) + term, data)) {
00077
00078 return 0;
00079 }
00080
00081 const char * pos = data.data();
00082 const char * end = pos + data.size();
00083 Xapian::termpos pos_last;
00084 if (!F_unpack_uint(&pos, end, &pos_last)) {
00085 throw Xapian::DatabaseCorruptError("Position list data corrupt");
00086 }
00087 if (pos == end) {
00088
00089 return 1;
00090 }
00091
00092
00093 BitReader rd(data, pos - data.data());
00094 Xapian::termpos pos_first = rd.decode(pos_last);
00095 Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
00096 return pos_size;
00097 }
00098
00100
00101 bool
00102 FlintPositionList::read_data(const FlintTable * table, Xapian::docid did,
00103 const string & tname)
00104 {
00105 LOGCALL_VOID(DB, "FlintPositionList::read_data", table | did | tname);
00106
00107 have_started = false;
00108 positions.clear();
00109
00110 string data;
00111 if (!table->get_exact_entry(F_pack_uint_preserving_sort(did) + tname, data)) {
00112
00113 current_pos = positions.begin();
00114 return false;
00115 }
00116
00117 const char * pos = data.data();
00118 const char * end = pos + data.size();
00119 Xapian::termpos pos_last;
00120 if (!F_unpack_uint(&pos, end, &pos_last)) {
00121 throw Xapian::DatabaseCorruptError("Position list data corrupt");
00122 }
00123 if (pos == end) {
00124
00125 positions.push_back(pos_last);
00126 current_pos = positions.begin();
00127 return true;
00128 }
00129
00130 BitReader rd(data, pos - data.data());
00131 Xapian::termpos pos_first = rd.decode(pos_last);
00132 Xapian::termpos pos_size = rd.decode(pos_last - pos_first) + 2;
00133 positions.resize(pos_size);
00134 positions[0] = pos_first;
00135 positions.back() = pos_last;
00136 rd.decode_interpolative(positions, 0, pos_size - 1);
00137
00138 current_pos = positions.begin();
00139 return true;
00140 }
00141
00142 Xapian::termcount
00143 FlintPositionList::get_size() const
00144 {
00145 LOGCALL(DB, Xapian::termcount, "FlintPositionList::get_size", NO_ARGS);
00146 RETURN(positions.size());
00147 }
00148
00149 Xapian::termpos
00150 FlintPositionList::get_position() const
00151 {
00152 LOGCALL(DB, Xapian::termpos, "FlintPositionList::get_position", NO_ARGS);
00153 Assert(have_started);
00154 RETURN(*current_pos);
00155 }
00156
00157 void
00158 FlintPositionList::next()
00159 {
00160 LOGCALL_VOID(DB, "FlintPositionList::next", NO_ARGS);
00161
00162 if (!have_started) {
00163 have_started = true;
00164 } else {
00165 Assert(!at_end());
00166 ++current_pos;
00167 }
00168 }
00169
00170 void
00171 FlintPositionList::skip_to(Xapian::termpos termpos)
00172 {
00173 LOGCALL_VOID(DB, "FlintPositionList::skip_to", termpos);
00174 if (!have_started) {
00175 have_started = true;
00176 }
00177 while (!at_end() && *current_pos < termpos) ++current_pos;
00178 }
00179
00180 bool
00181 FlintPositionList::at_end() const
00182 {
00183 LOGCALL(DB, bool, "FlintPositionList::at_end", NO_ARGS);
00184 RETURN(current_pos == positions.end());
00185 }