2 * Copyright (C) 2007-2009 Andre Noll <maan@systemlinux.org>
4 * Licensed under the GPL v2. For licencing details see COPYING.
7 /** \file mm.c Paraslash's mood methods. */
21 #define MOOD_COMPARATORS \
23 MC(LESS_OR_EQUAL, <=) \
29 MC(GREATER_OR_EQUAL, >=) \
31 #define MC(a, b) MC_ ## a,
32 enum mood_comparator_id
{MOOD_COMPARATORS NUM_MOOD_COMPARATORS
};
35 const char const *mood_comparators
[] = {MOOD_COMPARATORS
};
38 static int parse_mood_comparator(const char *word
)
42 for (i
= 0; i
< NUM_MOOD_COMPARATORS
; i
++)
43 if (!strcmp(word
, mood_comparators
[i
]))
45 return -E_MOOD_SYNTAX
;
48 static int compare_int32(int32_t a
, int32_t b
, enum mood_comparator_id id
)
55 case MC_LESS_OR_EQUAL
:
65 case MC_GREATER_OR_EQUAL
:
68 PARA_EMERG_LOG("BUG: invalid mood comparator\n");
71 return res
? 100 : -100;
74 static int mm_regex_parser(int argc
, char **argv
, void **private)
80 return -E_MOOD_SYNTAX
;
81 preg
= para_malloc(sizeof(*preg
));
82 ret
= para_regcomp(preg
, argv
[1], REG_EXTENDED
| REG_NOSUB
);
91 static int mm_regex_score_function(const regex_t
*preg
, const char *pattern
)
93 return regexec(preg
, pattern
, 0, NULL
, 0) == 0? 100 : -100;
96 static void mm_regex_cleanup(void *private)
98 regex_t
*preg
= private;
103 static int mm_artist_matches_score_function(__a_unused
const char *path
,
104 __a_unused
const struct afs_info
*afsi
,
105 const struct afh_info
*afhi
,
108 return mm_regex_score_function(private, afhi
->tags
.artist
);
111 static int mm_title_matches_score_function(__a_unused
const char *path
,
112 __a_unused
const struct afs_info
*afsi
,
113 const struct afh_info
*afhi
,
116 return mm_regex_score_function(private, afhi
->tags
.title
);
119 static int mm_album_matches_score_function(__a_unused
const char *path
,
120 __a_unused
const struct afs_info
*afsi
,
121 const struct afh_info
*afhi
,
124 return mm_regex_score_function(private, afhi
->tags
.album
);
127 static int mm_comment_matches_score_function(__a_unused
const char *path
,
128 __a_unused
const struct afs_info
*afsi
,
129 const struct afh_info
*afhi
,
132 return mm_regex_score_function(private, afhi
->tags
.comment
);
135 struct mm_year_data
{
136 /** The year given at the mood line. */
138 /** Used to detect Y2K issues. */
139 int32_t current_year
;
140 /** <, <=, =, !=, >=, or >. */
141 enum mood_comparator_id id
;
144 static int mm_year_parser(int argc
, char **argv
, void **private)
146 int ret
= -E_MOOD_SYNTAX
;
147 struct mm_year_data
*mmyd
= para_malloc(sizeof(*mmyd
));
153 ret
= parse_mood_comparator(argv
[1]);
157 ret
= para_atoi32(argv
[2], &mmyd
->year
);
160 current_time
= time(NULL
);
161 gmt
= gmtime(¤t_time
);
162 /* tm_year is the number of years since 1900 */
163 mmyd
->current_year
= gmt
->tm_year
+ 1900;
171 static int mm_year_score_function(__a_unused
const char *path
,
172 __a_unused
const struct afs_info
*afsi
,
173 const struct afh_info
*afhi
,
176 const struct mm_year_data
*mmyd
= private;
178 int ret
= para_atoi32(afhi
->tags
.year
, &tag_year
);
180 if (ret
< 0) /* year tag not present or not a number */
184 /* try to work around Y2K issues */
185 if (tag_year
< 100) {
187 if (tag_year
+ 100 <= mmyd
->current_year
)
188 tag_year
+= 100; /* assume tag_year >= 2000 */
190 return compare_int32(tag_year
, mmyd
->year
, mmyd
->id
);
193 static void mm_year_cleanup(void *private)
198 static int mm_no_attributes_set_parser(int argc
, __a_unused
char **argv
,
199 __a_unused
void **ignored
)
201 return argc
? -E_MOOD_SYNTAX
: 1;
204 static int mm_no_attributes_set_score_function(__a_unused
const char *path
,
205 const struct afs_info
*afsi
,
206 __a_unused
const struct afh_info
*afhi
,
207 __a_unused
const void *data
)
209 if (!afsi
->attributes
)
214 static int mm_path_matches_score_function(const char *path
,
215 __a_unused
const struct afs_info
*afsi
,
216 __a_unused
const struct afh_info
*afhi
,
219 if (fnmatch(data
, path
, 0))
224 static int mm_path_matches_parser(int argc
, char **argv
, void **data
)
227 return -E_MOOD_SYNTAX
;
228 *data
= para_strdup(argv
[1]);
232 static void mm_path_matches_cleanup(void *data
)
237 static int mm_is_set_parser(int argc
, char **argv
, void **bitnum
)
240 unsigned char c
, *res
;
243 return -E_MOOD_SYNTAX
;
244 ret
= get_attribute_bitnum_by_name(argv
[1], &c
);
247 res
= para_malloc(1);
253 static int mm_is_set_score_function(__a_unused
const char *path
,
254 __a_unused
const struct afs_info
*afsi
,
255 __a_unused
const struct afh_info
*afhi
,
258 const unsigned char *bn
= data
;
259 if (afsi
->attributes
& (1ULL << *bn
))
264 #define DEFINE_MOOD_METHOD(_name) \
265 .parser = mm_ ## _name ## _parser, \
266 .score_function = mm_ ## _name ## _score_function, \
269 #define DEFINE_MOOD_METHOD_WITH_CLEANUP(_name) \
270 DEFINE_MOOD_METHOD(_name), \
271 .cleanup = mm_ ## _name ## _cleanup
273 #define DEFINE_REGEX_MOOD_METHOD(_name) \
275 .parser = mm_regex_parser, \
276 .score_function = mm_ ## _name ## _score_function, \
277 .cleanup = mm_regex_cleanup
279 const struct mood_method mood_methods
[] = {
280 {DEFINE_MOOD_METHOD(no_attributes_set
)},
281 {DEFINE_MOOD_METHOD(is_set
)},
282 {DEFINE_MOOD_METHOD_WITH_CLEANUP(path_matches
)},
283 {DEFINE_MOOD_METHOD_WITH_CLEANUP(year
)},
284 {DEFINE_REGEX_MOOD_METHOD(artist_matches
)},
285 {DEFINE_REGEX_MOOD_METHOD(title_matches
)},
286 {DEFINE_REGEX_MOOD_METHOD(album_matches
)},
287 {DEFINE_REGEX_MOOD_METHOD(comment_matches
)},