root / tags / 1.0.8 / xapian-core / backends / flint / flint_cursor.h
| Revision 9280, 6.8 kB (checked in by olly, 16 months ago) | |
|---|---|
|
|
| Line | |
|---|---|
| 1 | /* bcursor.h: Interface to Btree cursors |
| 2 | * |
| 3 | * Copyright 1999,2000,2001 BrightStation PLC |
| 4 | * Copyright 2002,2003,2004,2006,2007 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 | #ifndef OM_HGUARD_FLINT_CURSOR_H |
| 23 | #define OM_HGUARD_FLINT_CURSOR_H |
| 24 | |
| 25 | #include <xapian/visibility.h> |
| 26 | |
| 27 | #include "flint_types.h" |
| 28 | |
| 29 | #include <string> |
| 30 | using std::string; |
| 31 | |
| 32 | #define BLK_UNUSED uint4(-1) |
| 33 | |
| 34 | class Cursor_ { |
| 35 | private: |
| 36 | // Prevent copying |
| 37 | Cursor_(const Cursor_ &); |
| 38 | Cursor_ & operator=(const Cursor_ &); |
| 39 | |
| 40 | public: |
| 41 | /// Constructor, to initialise important elements. |
| 42 | Cursor_() : p(0), c(-1), n(BLK_UNUSED), rewrite(false) |
| 43 | {} |
| 44 | |
| 45 | /// pointer to a block |
| 46 | byte * p; |
| 47 | /// offset in the block's directory |
| 48 | int c; |
| 49 | /** block number |
| 50 | * |
| 51 | * n is kept in tandem with p. The unassigned state is when |
| 52 | * p == 0 and n == BLK_UNUSED. |
| 53 | * |
| 54 | * Setting n to BLK_UNUSED is necessary in at least some cases. |
| 55 | */ |
| 56 | |
| 57 | uint4 n; |
| 58 | /// true if the block is not the same as on disk, and so needs rewriting |
| 59 | bool rewrite; |
| 60 | }; |
| 61 | |
| 62 | class FlintTable; |
| 63 | |
| 64 | /** A cursor pointing to a position in a Btree table, for reading several |
| 65 | * entries in order, or finding approximate matches. |
| 66 | */ |
| 67 | class XAPIAN_VISIBILITY_DEFAULT FlintCursor { |
| 68 | private: |
| 69 | /// Copying not allowed |
| 70 | FlintCursor(const FlintCursor &); |
| 71 | |
| 72 | /// Assignment not allowed |
| 73 | FlintCursor & operator=(const FlintCursor &); |
| 74 | |
| 75 | /** Whether the cursor is positioned at a valid entry. |
| 76 | * |
| 77 | * false initially, and after the cursor has dropped |
| 78 | * off either end of the list of items |
| 79 | */ |
| 80 | bool is_positioned; |
| 81 | |
| 82 | /** Whether the cursor is off the end of the table. |
| 83 | */ |
| 84 | bool is_after_end; |
| 85 | |
| 86 | /** Status of the current_tag member. */ |
| 87 | enum { UNREAD, UNCOMPRESSED, COMPRESSED } tag_status; |
| 88 | |
| 89 | /// The Btree table |
| 90 | FlintTable * B; |
| 91 | |
| 92 | /// Pointer to an array of Cursors |
| 93 | Cursor_ * C; |
| 94 | |
| 95 | /** The value of level in the Btree structure. */ |
| 96 | int level; |
| 97 | |
| 98 | /** Get the key. |
| 99 | * |
| 100 | * The key of the item at the cursor is copied into key. |
| 101 | * |
| 102 | * The cursor must be positioned before calling this method. |
| 103 | * |
| 104 | * e.g. |
| 105 | * |
| 106 | * FlintCursor BC(&btree); |
| 107 | * string key; |
| 108 | * |
| 109 | * // Now do something to each key in the Btree |
| 110 | * BC.find_entry(""); // must give result true |
| 111 | * |
| 112 | * while (BC.next()) { |
| 113 | * BC.get_key(&key); |
| 114 | * do_something_to(key); |
| 115 | * } |
| 116 | */ |
| 117 | void get_key(string * key) const; |
| 118 | |
| 119 | public: |
| 120 | /** Create a cursor attached to a Btree. |
| 121 | * |
| 122 | * Creates a cursor, which can be used to remember a position inside |
| 123 | * the B-tree. The position is simply the item (key and tag) to which |
| 124 | * the cursor points. A cursor is either positioned or unpositioned, |
| 125 | * and is initially unpositioned. |
| 126 | * |
| 127 | * NB: You must not try to use a FlintCursor after the Btree it is |
| 128 | * attached to is destroyed. It's safe to destroy the FlintCursor |
| 129 | * after the Btree though, you just may not use the FlintCursor. |
| 130 | */ |
| 131 | FlintCursor(FlintTable *B); |
| 132 | |
| 133 | /** Destroy the FlintCursor */ |
| 134 | ~FlintCursor(); |
| 135 | |
| 136 | /** Current key pointed to by cursor. |
| 137 | */ |
| 138 | string current_key; |
| 139 | |
| 140 | /** Current tag pointed to by cursor. You must call read_tag to |
| 141 | * make this value available. |
| 142 | */ |
| 143 | string current_tag; |
| 144 | |
| 145 | /** Read the tag from the table and store it in current_tag. |
| 146 | * |
| 147 | * Some cursor users don't need the tag, so for efficiency we |
| 148 | * only read it when asked to. |
| 149 | * |
| 150 | * @param keep_compressed Don't uncompress the tag - e.g. useful |
| 151 | * if it's just being opaquely copied |
| 152 | * (default: false). |
| 153 | * |
| 154 | * @return true if current_tag holds compressed data (always |
| 155 | * false if keep_compressed was false). |
| 156 | */ |
| 157 | bool read_tag(bool keep_compressed = false); |
| 158 | |
| 159 | /** Advance to the next key. |
| 160 | * |
| 161 | * If cursor is unpositioned, the result is simply false. |
| 162 | * |
| 163 | * If cursor is positioned, and points to the very last item in the |
| 164 | * Btree the cursor is made unpositioned, and the result is false. |
| 165 | * Otherwise the cursor is moved to the next item in the B-tree, |
| 166 | * and the result is true. |
| 167 | * |
| 168 | * Effectively, FlintCursor::next() loses the position of BC when it |
| 169 | * drops off the end of the list of items. If this is awkward, one can |
| 170 | * always arrange for a key to be present which has a rightmost |
| 171 | * position in a set of keys, |
| 172 | */ |
| 173 | bool next(); |
| 174 | |
| 175 | /** Move to the previous key. |
| 176 | * |
| 177 | * This is like FlintCursor::next, but BC is taken to the previous |
| 178 | * rather than next item. |
| 179 | */ |
| 180 | bool prev(); |
| 181 | |
| 182 | /** Position the cursor on the highest entry with key <= @a key. |
| 183 | * |
| 184 | * If the exact key is found in the table, the cursor will be |
| 185 | * set to point to it, and the method will return true. |
| 186 | * |
| 187 | * If the key is not found, the cursor will be set to point to |
| 188 | * the key preceding that asked for, and the method will return |
| 189 | * false. If there is no key preceding that asked for, the cursor |
| 190 | * will point to a null key. |
| 191 | * |
| 192 | * Note: Since the B-tree always contains a null key, which precedes |
| 193 | * everything, a call to FlintCursor::find_entry always results in a |
| 194 | * valid key being pointed to by the cursor. |
| 195 | * |
| 196 | * Note: Calling this method with a null key, then calling next() |
| 197 | * will leave the cursor pointing to the first key. |
| 198 | * |
| 199 | * @param key The key to look for in the table. |
| 200 | * |
| 201 | * @return true if the exact key was found in the table, false |
| 202 | * otherwise. |
| 203 | */ |
| 204 | bool find_entry(const string &key); |
| 205 | |
| 206 | /// Position the cursor on the highest entry with key < @a key. |
| 207 | void find_entry_lt(const string &key) { |
| 208 | if (find_entry(key)) prev(); |
| 209 | } |
| 210 | |
| 211 | /** Position the cursor on the lowest entry with key >= @a key. |
| 212 | * |
| 213 | * @return true if the exact key was found in the table, false |
| 214 | * otherwise. |
| 215 | */ |
| 216 | bool find_entry_ge(const string &key); |
| 217 | |
| 218 | /** Set the cursor to be off the end of the table. |
| 219 | */ |
| 220 | void to_end() { is_after_end = true; } |
| 221 | |
| 222 | /** Determine whether cursor is off the end of table. |
| 223 | * |
| 224 | * @return true if the cursor has been moved off the end of the |
| 225 | * table, past the last entry in it, and false otherwise. |
| 226 | */ |
| 227 | bool after_end() const { return is_after_end; } |
| 228 | |
| 229 | /** Delete the current key/tag pair, leaving the cursor on the next |
| 230 | * entry. |
| 231 | * |
| 232 | * @return false if the cursor ends up unpositioned. |
| 233 | */ |
| 234 | bool del(); |
| 235 | |
| 236 | /// Return a pointer to the FlintTable we're a cursor for. |
| 237 | FlintTable * get_table() const { return B; } |
| 238 | }; |
| 239 | |
| 240 | #endif /* OM_HGUARD_FLINT_CURSOR_H */ |
Note: See TracBrowser
for help on using the browser.
