int main(void) { RmTrie trie; rm_trie_init(&trie); GTimer *timer = g_timer_new(); g_timer_start(timer); char buf[1024]; int i = 0; while(fgets(buf, sizeof(buf), stdin)) { buf[strlen(buf) - 1] = 0; rm_trie_insert(&trie, buf, GUINT_TO_POINTER(++i)); memset(buf, 0, sizeof(buf)); } g_printerr("Took %2.5f to insert %d items\n", g_timer_elapsed(timer, NULL), i); rm_trie_print(&trie); memset(buf, 0, sizeof(buf)); rm_trie_build_path(&trie, rm_trie_search_node(&trie, "/usr/bin/rmlint"), buf, sizeof(buf)); g_printerr("=> %s\n", buf); g_timer_start(timer); const int N = 10000000; for(int x = 0; x < N; x++) { rm_trie_search(&trie, "/usr/bin/rmlint"); } g_printerr("Took %2.5f to search\n", g_timer_elapsed(timer, NULL)); g_printerr("%u\n", GPOINTER_TO_UINT(rm_trie_search(&trie, "/usr/bin/rmlint"))); g_printerr("%u\n", GPOINTER_TO_UINT(rm_trie_search(&trie, "/a/b/c"))); rm_trie_destroy(&trie); g_timer_destroy(timer); return 0; }
bool rm_trie_set_value(RmTrie *self, const char *path, void *data) { RmNode *find = rm_trie_search_node(self, path); if(find == NULL) { return false; } else { find->data = data; return true; } }
static bool rm_tm_count_files(RmTrie *count_tree, char **paths, RmSession *session) { if(*paths == NULL) { rm_log_error("No paths passed to rm_tm_count_files\n"); return false; } int fts_flags = FTS_COMFOLLOW; if(session->cfg->follow_symlinks) { fts_flags |= FTS_LOGICAL; } else { fts_flags |= FTS_PHYSICAL; } /* This tree stores the full file paths. It is joined into a full directory tree later. */ RmTrie file_tree; rm_trie_init(&file_tree); FTS *fts = fts_open(paths, fts_flags, NULL); if(fts == NULL) { rm_log_perror("fts_open failed"); return false; } FTSENT *ent = NULL; while((ent = fts_read(fts))) { /* Handle large files (where fts fails with FTS_NS) */ if(ent->fts_info == FTS_NS) { RmStat stat_buf; if(rm_sys_stat(ent->fts_path, &stat_buf) == -1) { rm_log_perror("stat(2) failed"); continue; } else { /* Must be a large file (or followed link to it) */ ent->fts_info = FTS_F; } } switch(ent->fts_info) { case FTS_ERR: case FTS_DC: /* Save this path as an error */ rm_trie_insert(&file_tree, ent->fts_path, GINT_TO_POINTER(true)); break; case FTS_F: case FTS_SL: case FTS_NS: case FTS_SLNONE: case FTS_DEFAULT: /* Save this path as countable file */ if(ent->fts_statp->st_size > 0) { rm_trie_insert(&file_tree, ent->fts_path, GINT_TO_POINTER(false)); } case FTS_D: case FTS_DNR: case FTS_DOT: case FTS_DP: case FTS_NSOK: default: /* other fts states, that do not count as errors or files */ break; } } if(fts_close(fts) != 0) { rm_log_perror("fts_close failed"); return false; } rm_trie_iter(&file_tree, NULL, true, false, rm_tm_count_art_callback, count_tree); /* Now flag everything as a no-go over the given paths, * otherwise we would continue merging till / with fatal consequences, * since / does not have more files as paths[0] */ for(int i = 0; paths[i]; ++i) { /* Just call the callback directly */ RmNode *node = rm_trie_search_node(&file_tree, paths[i]); if(node != NULL) { node->data = GINT_TO_POINTER(true); rm_tm_count_art_callback(&file_tree, node, 0, count_tree); } } #ifdef _RM_TREEMERGE_DEBUG rm_trie_print(count_tree); #endif rm_trie_destroy(&file_tree); return true; }
void *rm_trie_search(RmTrie *self, const char *path) { RmNode *find = rm_trie_search_node(self, path); return (find) ? find->data : NULL; }