| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- #include <string.h>
- #include "config.h"
- /**
- * btree - Efficient sorted associative container based on B-trees.
- *
- * This module provides an efficient in-memory lookup container that keeps a
- * set of pointers sorted using a user-defined search function.
- *
- * This module supports insertion, removal, lookup, and traversal using an
- * iterator system. Note that insertion and removal into/from a btree will
- * invalidate all iterators pointing to it (including the one passed to the
- * insertion or removal function).
- *
- * A B-tree (not to be confused with a binary tree) is a data structure that
- * performs insertion, removal, and lookup in O(log n) time per operation.
- * Although B-trees are typically used for databases and filesystems, this is
- * an in-memory implementation.
- *
- * Unlike functions like qsort, bsearch, and tsearch, btree does not take a
- * comparison function. It takes a binary search function, which is
- * theoretically equivalent but faster. Writing a binary search function
- * is more difficult than writing a comparison function, so a macro is provided
- * to make it much easier than doing either manually.
- *
- * Example:
- * #include <ccan/btree/btree.h>
- *
- * #include <errno.h>
- * #include <stdlib.h>
- * #include <stdio.h>
- * #include <string.h>
- *
- * struct word {
- * char *word;
- * char *letter_set;
- * };
- *
- * //Define the ordering function order_by_letter_set
- * static btree_search_implement
- * (
- * order_by_letter_set,
- * struct word *,
- * int c = strcmp(a->letter_set, b->letter_set),
- * c == 0,
- * c < 0
- * )
- *
- * struct word *new_word(const char *line);
- * char *chomp(char *str);
- * char *make_letter_set(char *str);
- *
- * static void insert_word(struct btree *btree, struct word *word)
- * {
- * btree_iterator iter;
- *
- * //Position iterator after existing words with this letter set.
- * btree_find_last(btree, word, iter);
- *
- * //Insert new word at iterator position.
- * btree_insert_at(iter, word);
- * }
- *
- * static void print_anagrams(struct btree *btree, char *line)
- * {
- * btree_iterator iter, end;
- * struct word key = {
- * NULL,
- * make_letter_set(line)
- * };
- *
- * //Find first matching word.
- * if (!btree_find_first(btree, &key, iter)) {
- * printf("\t(none)\n");
- * return;
- * }
- *
- * btree_find_last(btree, &key, end);
- *
- * //Traverse matching words.
- * for (; btree_deref(iter) && btree_cmp_iters(iter, end) < 0;
- * btree_next(iter))
- * {
- * struct word *word = iter->item;
- * printf("\t%s\n", word->word);
- * }
- * }
- *
- * static int destroy_word(struct word *word, void *ctx)
- * {
- * (void) ctx;
- *
- * free(word->word);
- * free(word->letter_set);
- * free(word);
- *
- * return 1;
- * }
- *
- * static struct btree *read_dictionary(const char *filename)
- * {
- * FILE *f;
- * char line[256];
- *
- * //Construct new btree with the ordering function order_by_letter_set .
- * struct btree *btree = btree_new(order_by_letter_set);
- *
- * f = fopen(filename, "r");
- * if (!f)
- * goto fail;
- *
- * //Set the destroy callback so btree_free will automatically
- * //free our items. Setting btree->destroy is optional.
- * btree->destroy = (btree_action_t)destroy_word;
- *
- * while (fgets(line, sizeof(line), f)) {
- * struct word *word = new_word(line);
- * if (!word)
- * continue;
- * insert_word(btree, word);
- * }
- *
- * if (ferror(f)) {
- * fclose(f);
- * goto fail;
- * }
- * if (fclose(f))
- * goto fail;
- *
- * return btree;
- *
- * fail:
- * btree_delete(btree);
- * fprintf(stderr, "%s: %s\n", filename, strerror(errno));
- * return NULL;
- * }
- *
- * int main(int argc, char *argv[])
- * {
- * struct btree *btree;
- * char line[256];
- *
- * if (argc != 2) {
- * fprintf(stderr,
- * "Usage: %s dictionary-file\n"
- * "Example:\n"
- * "\t%s /usr/share/dict/words\n"
- * "\n"
- * , argv[0], argv[0]);
- * return 1;
- * }
- *
- * printf("Indexing...\n");
- * btree = read_dictionary(argv[1]);
- * printf("Dictionary has %ld words\n", (long)btree->count);
- *
- * for (;;) {
- * printf("> ");
- * if (!fgets(line, sizeof(line), stdin))
- * break;
- * chomp(line);
- * if (!*line)
- * break;
- *
- * printf("Anagrams of \"%s\":\n", line);
- * print_anagrams(btree, line);
- * }
- *
- * printf("Cleaning up...\n");
- * btree_delete(btree);
- *
- * return 0;
- * }
- *
- * struct word *new_word(const char *line)
- * {
- * struct word *word;
- * char *letter_set = make_letter_set(strdup(line));
- *
- * //Discard lines with no letters
- * if (!*letter_set) {
- * free(letter_set);
- * return NULL;
- * }
- *
- * word = malloc(sizeof(struct word));
- * word->word = chomp(strdup(line));
- * word->letter_set = letter_set;
- *
- * return word;
- * }
- *
- * //Remove trailing newline (if present).
- * char *chomp(char *str)
- * {
- * char *end = strchr(str, '\0') - 1;
- * if (*str && *end == '\n')
- * *end = 0;
- * return str;
- * }
- *
- * //Remove all characters but letters, make letters lowercase, and sort them.
- * char *make_letter_set(char *str)
- * {
- * size_t count[26] = {0};
- * size_t i, j;
- * char *o = str;
- *
- * for (i=0; str[i]; i++) {
- * char c = str[i];
- * if (c >= 'A' && c <= 'Z')
- * c += 'a'-'A';
- * if (c >= 'a' && c <= 'z')
- * count[c - 'a']++;
- * }
- *
- * for (i = 0; i < 26; i++) {
- * for (j = 0; j < count[i]; j++)
- * *o++ = 'a' + i;
- * }
- * *o = '\0';
- *
- * return str;
- * }
- *
- * Author: Joey Adams <joeyadams3.14159@gmail.com>
- * License: MIT
- * Version: 0.2
- */
- int main(int argc, char *argv[])
- {
- /* Expect exactly one argument */
- if (argc != 2)
- return 1;
- if (strcmp(argv[1], "depends") == 0) {
- /* Nothing */
- return 0;
- }
- return 1;
- }
|