Some improvements to the trie:
authorFlorent Bruneau <florent.bruneau@polytechnique.org>
Wed, 17 Sep 2008 20:19:53 +0000 (22:19 +0200)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Wed, 17 Sep 2008 20:19:53 +0000 (22:19 +0200)
  - add trie_prefix to check if the trie contains a prefix for    a string.
  - add comments
  - lock the trie_t structure, not only its content.

Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
common/trie.c
common/trie.h

index 59f1a9f..7d75d69 100644 (file)
@@ -108,6 +108,12 @@ static inline bool trie_entry_match(const trie_t *trie,
     return !!(strcmp(array_ptr(trie->c, entry->c_offset), key) == 0);
 }
 
+static inline bool trie_entry_prefix(const trie_t *trie,
+                                     const trie_entry_t *entry, const char *key)
+{
+    return !!(strncmp(array_ptr(trie->c, entry->c_offset), key, entry->c_len) == 0);
+}
+
 static inline bool trie_entry_is_leaf(const trie_entry_t *entry)
 {
     return entry->children_len == 0;
@@ -297,6 +303,30 @@ bool trie_lookup(const trie_t *trie, const char *key)
     }
 }
 
+bool trie_prefix(const trie_t *trie, const char *key)
+{
+    assert(trie->keys.len == 0L && "Can't lookup: trie not compiled");
+    if (trie->entries.len == 0) {
+        return false;
+    } else {
+        trie_entry_t *current = array_ptr(trie->entries, 0);
+        while (true) {
+            int pos = 0;
+            if (trie_entry_is_leaf(current)) {
+                return trie_entry_prefix(trie, current, key);
+            } else if (trie_entry_c_match(trie, current, key, &pos)) {
+                key += pos;
+                current = trie_entry_child(trie, current, key);
+                if (current == NULL) {
+                    return false;
+                }
+            } else {
+                return false;
+            }
+        }
+    }
+}
+
 void trie_lock(trie_t *trie)
 {
     if (trie->locked) {
@@ -311,6 +341,12 @@ void trie_lock(trie_t *trie)
         array_unlock(trie->entries);
         return;
     }
+    if (mlock(trie, sizeof(trie_t)) != 0) {
+        UNIXERR("mlock");
+        array_unlock(trie->entries);
+        array_unlock(trie->c);
+        return;
+    }
     trie->locked = true;
 }
 
@@ -321,6 +357,7 @@ void trie_unlock(trie_t *trie)
     }
     array_unlock(trie->entries);
     array_unlock(trie->c);
+    munlock(trie, sizeof(trie_t));
     trie->locked = false;
 }
 
index ddf984a..85ce031 100644 (file)
@@ -44,21 +44,56 @@ PARRAY(trie_t)
 trie_t *trie_new(void);
 void trie_delete(trie_t **trie);
 
+/** Add a string in the trie.
+ * \ref trie_compile.
+ */
 __attribute__((nonnull(1,2)))
-void trie_insert(trie_t *trie, const charkey);
+void trie_insert(trie_t *trie, const char *key);
 
+/** Compile the trie.
+ * A trie must be compiled before lookup is possible. Compiling the trie
+ * consists in building the tree.
+ *
+ * \param memlock if true, the trie is locked into the RAM (mlock).
+ *
+ * Usage of a trie:
+ *   trie_insert(trie, ...);
+ *   trie_insert(trie, ...);
+ *   ...
+ *   trie_insert(trie, ...);
+ *
+ *   trie_compile(trie, lock);
+ *
+ *   trie_lookup(trie, ...);
+ *   trie_lookup(trie, ...);
+ */
 __attribute__((nonnull(1)))
 void trie_compile(trie_t *trie, bool memlock);
 
+/** Lock the trie into memory.
+ * \ref trie_unlock
+ */
 __attribute__((nonnull(1)))
 void trie_lock(trie_t *trie);
 
+/** Unlock the trie.
+ * \ref trie_lock
+ */
 __attribute__((nonnull(1)))
 void trie_unlock(trie_t *trie);
 
+/** Check if the trie contains \p key.
+ */
 __attribute__((nonnull(1,2)))
-bool trie_lookup(const trie_t *trie, const charkey);
+bool trie_lookup(const trie_t *trie, const char *key);
 
+/** Check if the trie contains a prefix of \p key.
+ */
+__attribute__((nonnull(1,2)))
+bool trie_prefix(const trie_t *trie, const char *key);
+
+/** Show the content of the trie and computes statistics.
+ */
 __attribute__((nonnull(1)))
 void trie_inspect(const trie_t *trie, bool show_content);