X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=mm.c;h=ead20681f781427f1c1d27aec015bc64f79ff9e0;hp=0130cbcb81510f0d71a4b63c3e2f568aaa54670b;hb=fcb24360b1b14c9fe0e510282cf85f4e112eaf23;hpb=9242741b62d726e7b673a3b10c62bbc8509a75ef diff --git a/mm.c b/mm.c index 0130cbcb..ead20681 100644 --- a/mm.c +++ b/mm.c @@ -32,7 +32,7 @@ enum mood_comparator_id {MOOD_COMPARATORS NUM_MOOD_COMPARATORS}; #undef MC #define MC(a, b) # b, -const char const *mood_comparators[] = {MOOD_COMPARATORS}; +static const char const *mood_comparators[] = {MOOD_COMPARATORS}; #undef MC static int parse_mood_comparator(const char *word) @@ -45,25 +45,34 @@ static int parse_mood_comparator(const char *word) return -E_MOOD_SYNTAX; } -static int compare_int32(int32_t a, int32_t b, enum mood_comparator_id id) +struct mm_compare_num_data { + /** <, <=, =, !=, >=, or >. */ + enum mood_comparator_id id; + /** The value given at the mood line. */ + int32_t arg; +}; + +static int mm_compare_num_score_function(int32_t val, + const struct mm_compare_num_data *cnd) { int res; + int32_t arg = cnd->arg; - switch (id) { + switch (cnd->id) { case MC_LESS: - res = a < b; break; + res = val < arg; break; case MC_LESS_OR_EQUAL: - res = a <= b; break; + res = val <= arg; break; case MC_EQUAL: case MC_EQUAL2: - res = a == b; break; + res = val == arg; break; case MC_NOT_EQUAL: case MC_NOT_EQUAL2: - res = a != b; break; + res = val != arg; break; case MC_GREATER: - res = a > b; break; + res = val > arg; break; case MC_GREATER_OR_EQUAL: - res = a >= b; break; + res = val >= arg; break; default: PARA_EMERG_LOG("BUG: invalid mood comparator\n"); exit(EXIT_FAILURE); @@ -71,13 +80,126 @@ static int compare_int32(int32_t a, int32_t b, enum mood_comparator_id id) return res? 100 : -100; } +static int mm_compare_num_parser(int argc, char **argv, void **private) +{ + int ret; + enum mood_comparator_id id; + int32_t arg; + struct mm_compare_num_data *cnd; + if (argc != 2) + return -E_MOOD_SYNTAX; + ret = parse_mood_comparator(argv[1]); + if (ret < 0) + return ret; + id = ret; + ret = para_atoi32(argv[2], &arg); + if (ret < 0) + return ret; + cnd = para_malloc(sizeof(struct mm_compare_num_data)); + cnd->id = id; + cnd->arg = arg; + *private = cnd; + return 1; +} + +static int mm_regex_parser(int argc, char **argv, void **private) +{ + regex_t *preg; + int ret; + + if (argc != 1) + return -E_MOOD_SYNTAX; + preg = para_malloc(sizeof(*preg)); + ret = para_regcomp(preg, argv[1], REG_EXTENDED | REG_NOSUB); + if (ret < 0) { + free(preg); + return ret; + } + *private = preg; + return 1; +} + +static int mm_regex_score_function(const regex_t *preg, const char *pattern) +{ + return regexec(preg, pattern, 0, NULL, 0) == 0? 100 : -100; +} + +static void mm_regex_cleanup(void *private) +{ + regex_t *preg = private; + regfree(preg); + free(preg); +} + +static int mm_artist_matches_score_function(__a_unused const char *path, + __a_unused const struct afs_info *afsi, + const struct afh_info *afhi, + const void *private) +{ + return mm_regex_score_function(private, afhi->tags.artist); +} + +static int mm_title_matches_score_function(__a_unused const char *path, + __a_unused const struct afs_info *afsi, + const struct afh_info *afhi, + const void *private) +{ + return mm_regex_score_function(private, afhi->tags.title); +} + +static int mm_album_matches_score_function(__a_unused const char *path, + __a_unused const struct afs_info *afsi, + const struct afh_info *afhi, + const void *private) +{ + return mm_regex_score_function(private, afhi->tags.album); +} + +static int mm_comment_matches_score_function(__a_unused const char *path, + __a_unused const struct afs_info *afsi, + const struct afh_info *afhi, + const void *private) +{ + return mm_regex_score_function(private, afhi->tags.comment); +} + +static int mm_bitrate_score_function(__a_unused const char *path, + __a_unused const struct afs_info *afsi, + const struct afh_info *afhi, + const void *private) +{ + return mm_compare_num_score_function(afhi->bitrate, private); +} + +static int mm_frequency_score_function(__a_unused const char *path, + __a_unused const struct afs_info *afsi, + const struct afh_info *afhi, + const void *private) +{ + return mm_compare_num_score_function(afhi->frequency, private); +} + +static int mm_channels_score_function(__a_unused const char *path, + __a_unused const struct afs_info *afsi, + const struct afh_info *afhi, + const void *private) +{ + return mm_compare_num_score_function(afhi->channels, private); +} + +static int mm_num_played_score_function(__a_unused const char *path, + const struct afs_info *afsi, + __a_unused const struct afh_info *afhi, + const void *private) +{ + return mm_compare_num_score_function(afsi->num_played, private); +} + struct mm_year_data { - /** The year given at the mood line. */ - int32_t year; + /** Comparator and year given at the mood line. */ + struct mm_compare_num_data *cnd; /** Used to detect Y2K issues. */ int32_t current_year; - /** <, <=, =, !=, >=, or >. */ - enum mood_comparator_id id; }; static int mm_year_parser(int argc, char **argv, void **private) @@ -87,13 +209,7 @@ static int mm_year_parser(int argc, char **argv, void **private) time_t current_time; struct tm *gmt; - if (argc != 2) - goto err; - ret = parse_mood_comparator(argv[1]); - mmyd->id = ret; - if (ret < 0) - goto err; - ret = para_atoi32(argv[2], &mmyd->year); + ret = mm_compare_num_parser(argc, argv, (void **)&mmyd->cnd); if (ret < 0) goto err; current_time = time(NULL); @@ -126,12 +242,15 @@ static int mm_year_score_function(__a_unused const char *path, if (tag_year + 100 <= mmyd->current_year) tag_year += 100; /* assume tag_year >= 2000 */ } - return compare_int32(tag_year, mmyd->year, mmyd->id); + return mm_compare_num_score_function(tag_year, mmyd->cnd); } static void mm_year_cleanup(void *private) { - free(private); + struct mm_year_data *mmyd = private; + + free(mmyd->cnd); + free(mmyd); } static int mm_no_attributes_set_parser(int argc, __a_unused char **argv, @@ -209,11 +328,29 @@ static int mm_is_set_score_function(__a_unused const char *path, DEFINE_MOOD_METHOD(_name), \ .cleanup = mm_ ## _name ## _cleanup +#define DEFINE_REGEX_MOOD_METHOD(_name) \ + .name = #_name, \ + .parser = mm_regex_parser, \ + .score_function = mm_ ## _name ## _score_function, \ + .cleanup = mm_regex_cleanup + +#define DEFINE_COMPARE_NUM_MOOD_METHOD(_name) \ + .name = #_name, \ + .parser = mm_compare_num_parser, \ + .score_function = mm_ ## _name ## _score_function + const struct mood_method mood_methods[] = { {DEFINE_MOOD_METHOD(no_attributes_set)}, {DEFINE_MOOD_METHOD(is_set)}, {DEFINE_MOOD_METHOD_WITH_CLEANUP(path_matches)}, {DEFINE_MOOD_METHOD_WITH_CLEANUP(year)}, + {DEFINE_REGEX_MOOD_METHOD(artist_matches)}, + {DEFINE_REGEX_MOOD_METHOD(title_matches)}, + {DEFINE_REGEX_MOOD_METHOD(album_matches)}, + {DEFINE_REGEX_MOOD_METHOD(comment_matches)}, + {DEFINE_COMPARE_NUM_MOOD_METHOD(bitrate)}, + {DEFINE_COMPARE_NUM_MOOD_METHOD(frequency)}, + {DEFINE_COMPARE_NUM_MOOD_METHOD(channels)}, + {DEFINE_COMPARE_NUM_MOOD_METHOD(num_played)}, {.parser = NULL} }; -