2 * Copyright 2004-2007 Timo Hirvonen
11 struct keyval
*comments_dup(const struct keyval
*comments
)
16 for (i
= 0; comments
[i
].key
; i
++)
18 c
= xnew(struct keyval
, i
+ 1);
19 for (i
= 0; comments
[i
].key
; i
++) {
20 c
[i
].key
= xstrdup(comments
[i
].key
);
21 c
[i
].val
= xstrdup(comments
[i
].val
);
28 void comments_free(struct keyval
*comments
)
32 for (i
= 0; comments
[i
].key
; i
++) {
33 free(comments
[i
].key
);
34 free(comments
[i
].val
);
39 const char *comments_get_val(const struct keyval
*comments
, const char *key
)
43 for (i
= 0; comments
[i
].key
; i
++) {
44 if (strcasecmp(comments
[i
].key
, key
) == 0)
45 return comments
[i
].val
;
50 const char *comments_get_albumartist(const struct keyval
*comments
)
52 const char *val
= comments_get_val(comments
, "albumartist");
54 val
= comments_get_val(comments
, "artist");
58 int comments_get_int(const struct keyval
*comments
, const char *key
)
63 val
= comments_get_val(comments
, key
);
66 if (str_to_int(val
, &ival
) == -1)
71 /* Return date as an integer in the form YYYYMMDD, for sorting purposes.
72 * This function is not year 10000 compliant. */
73 int comments_get_date(const struct keyval
*comments
, const char *key
)
80 val
= comments_get_val(comments
, key
);
84 year
= strtol(val
, &endptr
, 10);
85 /* Looking for a four-digit number */
86 if (year
< 1000 || year
> 9999)
90 if (*endptr
== '-' || *endptr
== ' ' || *endptr
== '/') {
91 month
= strtol(endptr
+1, &endptr
, 10);
92 if (month
< 1 || month
> 12)
97 if (*endptr
== '-' || *endptr
== ' ' || *endptr
== '/') {
98 day
= strtol(endptr
+1, &endptr
, 10);
99 if (day
< 1 || day
> 31)
108 static const char *interesting
[] = {
109 "artist", "album", "title", "tracknumber", "discnumber", "genre",
110 "date", "compilation", "albumartist", "artistsort", "albumartistsort",
111 "replaygain_track_gain",
112 "replaygain_track_peak",
113 "replaygain_album_gain",
114 "replaygain_album_peak",
122 { "album_artist", "albumartist" },
123 { "album artist", "albumartist" },
124 { "disc", "discnumber" },
125 { "track", "tracknumber" },
129 static const char *fix_key(const char *key
)
133 for (i
= 0; interesting
[i
]; i
++) {
134 if (!strcasecmp(key
, interesting
[i
]))
135 return interesting
[i
];
137 for (i
= 0; key_map
[i
].old
; i
++) {
138 if (!strcasecmp(key
, key_map
[i
].old
))
139 return key_map
[i
].new;
144 int comments_add(struct growing_keyvals
*c
, const char *key
, char *val
)
146 int i
, n
= c
->count
+ 1;
154 if (!strcmp(key
, "tracknumber") || !strcmp(key
, "discnumber")) {
155 char *slash
= strchr(val
, '/');
160 /* don't add duplicates. can't use comments_get_val() */
161 for (i
= 0; i
< c
->count
; i
++) {
162 if (!strcasecmp(key
, c
->comments
[i
].key
) && !strcmp(val
, c
->comments
[i
].val
)) {
170 c
->comments
= xrenew(struct keyval
, c
->comments
, n
);
174 c
->comments
[c
->count
].key
= xstrdup(key
);
175 c
->comments
[c
->count
].val
= val
;
180 int comments_add_const(struct growing_keyvals
*c
, const char *key
, const char *val
)
182 return comments_add(c
, key
, xstrdup(val
));
185 void comments_terminate(struct growing_keyvals
*c
)
187 int alloc
= c
->count
+ 1;
189 if (alloc
> c
->alloc
) {
190 c
->comments
= xrenew(struct keyval
, c
->comments
, alloc
);
193 c
->comments
[c
->count
].key
= NULL
;
194 c
->comments
[c
->count
].val
= NULL
;