_info 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. #include <string.h>
  2. #include "config.h"
  3. /**
  4. * btree - Efficient sorted associative container based on B-trees.
  5. *
  6. * This module provides an efficient in-memory lookup container that keeps a
  7. * set of pointers sorted using a user-defined search function.
  8. *
  9. * This module supports insertion, removal, lookup, and traversal using an
  10. * iterator system. Note that insertion and removal into/from a btree will
  11. * invalidate all iterators pointing to it (including the one passed to the
  12. * insertion or removal function).
  13. *
  14. * A B-tree (not to be confused with a binary tree) is a data structure that
  15. * performs insertion, removal, and lookup in O(log n) time per operation.
  16. * Although B-trees are typically used for databases and filesystems, this is
  17. * an in-memory implementation.
  18. *
  19. * Unlike functions like qsort, bsearch, and tsearch, btree does not take a
  20. * comparison function. It takes a binary search function, which is
  21. * theoretically equivalent but faster. Writing a binary search function
  22. * is more difficult than writing a comparison function, so a macro is provided
  23. * to make it much easier than doing either manually.
  24. *
  25. * Example:
  26. * #include <ccan/btree/btree.h>
  27. *
  28. * #include <errno.h>
  29. * #include <stdlib.h>
  30. * #include <stdio.h>
  31. * #include <string.h>
  32. *
  33. * struct word {
  34. * char *word;
  35. * char *letter_set;
  36. * };
  37. *
  38. * //Define the ordering function order_by_letter_set
  39. * static btree_search_implement
  40. * (
  41. * order_by_letter_set,
  42. * struct word *,
  43. * int c = strcmp(a->letter_set, b->letter_set),
  44. * c == 0,
  45. * c < 0
  46. * )
  47. *
  48. * struct word *new_word(const char *line);
  49. * char *chomp(char *str);
  50. * char *make_letter_set(char *str);
  51. *
  52. * static void insert_word(struct btree *btree, struct word *word)
  53. * {
  54. * btree_iterator iter;
  55. *
  56. * //Position iterator after existing words with this letter set.
  57. * btree_find_last(btree, word, iter);
  58. *
  59. * //Insert new word at iterator position.
  60. * btree_insert_at(iter, word);
  61. * }
  62. *
  63. * static void print_anagrams(struct btree *btree, char *line)
  64. * {
  65. * btree_iterator iter, end;
  66. * struct word key = {
  67. * NULL,
  68. * make_letter_set(line)
  69. * };
  70. *
  71. * //Find first matching word.
  72. * if (!btree_find_first(btree, &key, iter)) {
  73. * printf("\t(none)\n");
  74. * return;
  75. * }
  76. *
  77. * btree_find_last(btree, &key, end);
  78. *
  79. * //Traverse matching words.
  80. * for (; btree_deref(iter) && btree_cmp_iters(iter, end) < 0;
  81. * btree_next(iter))
  82. * {
  83. * struct word *word = iter->item;
  84. * printf("\t%s\n", word->word);
  85. * }
  86. * }
  87. *
  88. * static int destroy_word(struct word *word, void *ctx)
  89. * {
  90. * (void) ctx;
  91. *
  92. * free(word->word);
  93. * free(word->letter_set);
  94. * free(word);
  95. *
  96. * return 1;
  97. * }
  98. *
  99. * static struct btree *read_dictionary(const char *filename)
  100. * {
  101. * FILE *f;
  102. * char line[256];
  103. *
  104. * //Construct new btree with the ordering function order_by_letter_set .
  105. * struct btree *btree = btree_new(order_by_letter_set);
  106. *
  107. * f = fopen(filename, "r");
  108. * if (!f)
  109. * goto fail;
  110. *
  111. * //Set the destroy callback so btree_free will automatically
  112. * //free our items. Setting btree->destroy is optional.
  113. * btree->destroy = (btree_action_t)destroy_word;
  114. *
  115. * while (fgets(line, sizeof(line), f)) {
  116. * struct word *word = new_word(line);
  117. * if (!word)
  118. * continue;
  119. * insert_word(btree, word);
  120. * }
  121. *
  122. * if (ferror(f)) {
  123. * fclose(f);
  124. * goto fail;
  125. * }
  126. * if (fclose(f))
  127. * goto fail;
  128. *
  129. * return btree;
  130. *
  131. * fail:
  132. * btree_delete(btree);
  133. * fprintf(stderr, "%s: %s\n", filename, strerror(errno));
  134. * return NULL;
  135. * }
  136. *
  137. * int main(int argc, char *argv[])
  138. * {
  139. * struct btree *btree;
  140. * char line[256];
  141. *
  142. * if (argc != 2) {
  143. * fprintf(stderr,
  144. * "Usage: %s dictionary-file\n"
  145. * "Example:\n"
  146. * "\t%s /usr/share/dict/words\n"
  147. * "\n"
  148. * , argv[0], argv[0]);
  149. * return 1;
  150. * }
  151. *
  152. * printf("Indexing...\n");
  153. * btree = read_dictionary(argv[1]);
  154. * printf("Dictionary has %ld words\n", (long)btree->count);
  155. *
  156. * for (;;) {
  157. * printf("> ");
  158. * if (!fgets(line, sizeof(line), stdin))
  159. * break;
  160. * chomp(line);
  161. * if (!*line)
  162. * break;
  163. *
  164. * printf("Anagrams of \"%s\":\n", line);
  165. * print_anagrams(btree, line);
  166. * }
  167. *
  168. * printf("Cleaning up...\n");
  169. * btree_delete(btree);
  170. *
  171. * return 0;
  172. * }
  173. *
  174. * struct word *new_word(const char *line)
  175. * {
  176. * struct word *word;
  177. * char *letter_set = make_letter_set(strdup(line));
  178. *
  179. * //Discard lines with no letters
  180. * if (!*letter_set) {
  181. * free(letter_set);
  182. * return NULL;
  183. * }
  184. *
  185. * word = malloc(sizeof(struct word));
  186. * word->word = chomp(strdup(line));
  187. * word->letter_set = letter_set;
  188. *
  189. * return word;
  190. * }
  191. *
  192. * //Remove trailing newline (if present).
  193. * char *chomp(char *str)
  194. * {
  195. * char *end = strchr(str, '\0') - 1;
  196. * if (*str && *end == '\n')
  197. * *end = 0;
  198. * return str;
  199. * }
  200. *
  201. * //Remove all characters but letters, make letters lowercase, and sort them.
  202. * char *make_letter_set(char *str)
  203. * {
  204. * size_t count[26] = {0};
  205. * size_t i, j;
  206. * char *o = str;
  207. *
  208. * for (i=0; str[i]; i++) {
  209. * char c = str[i];
  210. * if (c >= 'A' && c <= 'Z')
  211. * c += 'a'-'A';
  212. * if (c >= 'a' && c <= 'z')
  213. * count[c - 'a']++;
  214. * }
  215. *
  216. * for (i = 0; i < 26; i++) {
  217. * for (j = 0; j < count[i]; j++)
  218. * *o++ = 'a' + i;
  219. * }
  220. * *o = '\0';
  221. *
  222. * return str;
  223. * }
  224. *
  225. * Author: Joey Adams <joeyadams3.14159@gmail.com>
  226. * License: MIT
  227. * Version: 0.2
  228. */
  229. int main(int argc, char *argv[])
  230. {
  231. /* Expect exactly one argument */
  232. if (argc != 2)
  233. return 1;
  234. if (strcmp(argv[1], "depends") == 0) {
  235. /* Nothing */
  236. return 0;
  237. }
  238. return 1;
  239. }