static void visitTag(struct client *client, struct strset *set, struct song *song, enum tag_type tagType) { struct tag *tag = song->tag; bool found = false; if (tagType == LOCATE_TAG_FILE_TYPE) { song_print_uri(client, song); return; } if (!tag) return; for (unsigned i = 0; i < tag->num_items; i++) { if (tag->items[i]->type == tagType) { strset_add(set, tag->items[i]->value); found = true; } } if (!found) strset_add(set, ""); }
int cmd_purge(int argc, char *argv[]) { storage_t storage; strset_t backups; strset_t objects; const char *elem; struct mark_backup_args args; if (argc != 2) { int help_argc = 2; char *help_argv[] = { "help_err", "purge", NULL }; return cmd_help_err(help_argc, help_argv); } if ((storage = storage_new(argv[1], false, true)) == NULL) logger(LOG_ERROR, "unable to open storage: %s", argv[1]); if (!storage_lock(storage, true, options_get()->force)) logger(LOG_ERROR, "backup directory locked, use -f to force operation"); backups = strset_new(); objects = strset_new(); /* Get the list of backups. */ elem = storage_list(storage, "backups"); while (elem != NULL) { strset_add(backups, elem); elem = storage_list(storage, NULL); } /* Get the list of objects. */ elem = storage_list(storage, "objects"); while (elem != NULL) { strset_add(objects, elem); elem = storage_list(storage, NULL); } /* ** For each backup, call mark_backup, which will mark all the objects of a ** backup as used (it will actually remove them from the `objects` strset. */ args.objects = objects; args.storage = storage; strset_foreach(backups, mark_backup, &args); /* Delete every object remaining in the `objects` strset. */ strset_foreach(objects, delete_object, (void *) storage); strset_delete(backups); strset_delete(objects); storage_unlock(storage); storage_delete(storage); return EXIT_SUCCESS; }
static void visit_tag(struct visit_data *data, const struct tag *tag) { if (tag->time > 0) stats.song_duration += tag->time; for (unsigned i = 0; i < tag->num_items; ++i) { const struct tag_item *item = tag->items[i]; switch (item->type) { case TAG_ARTIST: strset_add(data->artists, item->value); break; case TAG_ALBUM: strset_add(data->albums, item->value); break; default: break; } } }
int main(void) { struct strset set; const char str[] = "hello"; const char none[] = ""; char *dup = strdup(str); /* This is how many tests you plan to run */ plan_tests(36); strset_init(&set); ok1(!strset_get(&set, str)); ok1(errno == ENOENT); ok1(!strset_get(&set, none)); ok1(errno == ENOENT); ok1(!strset_del(&set, str)); ok1(errno == ENOENT); ok1(!strset_del(&set, none)); ok1(errno == ENOENT); ok1(strset_add(&set, str)); ok1(strset_get(&set, str)); /* We compare the string, not the pointer. */ ok1(strset_get(&set, dup)); ok1(!strset_get(&set, none)); ok1(errno == ENOENT); /* Add of duplicate should fail. */ ok1(!strset_add(&set, dup)); ok1(errno == EEXIST); /* Delete should return original string. */ ok1(strset_del(&set, dup) == str); ok1(!strset_get(&set, str)); ok1(errno == ENOENT); ok1(!strset_get(&set, none)); ok1(errno == ENOENT); /* Try insert and delete of empty string. */ ok1(strset_add(&set, none)); ok1(strset_get(&set, none)); ok1(!strset_get(&set, str)); ok1(errno == ENOENT); /* Delete should return original string. */ ok1(strset_del(&set, "") == none); ok1(!strset_get(&set, str)); ok1(errno == ENOENT); ok1(!strset_get(&set, none)); ok1(errno == ENOENT); /* Both at once... */ ok1(strset_add(&set, none)); ok1(strset_add(&set, str)); ok1(strset_get(&set, str)); ok1(strset_get(&set, none)); ok1(strset_del(&set, "") == none); ok1(strset_del(&set, dup) == str); ok1(set.u.n == NULL); free(dup); /* This exits depending on whether all tests passed */ return exit_status(); }