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 int comments_get_int(const struct keyval
*comments
, const char *key
)
55 val
= comments_get_val(comments
, key
);
58 if (str_to_int(val
, &ival
) == -1)
63 /* Return date as an integer in the form YYYYMMDD, for sorting purposes.
64 * This function is not year 10000 compliant. */
65 int comments_get_date(const struct keyval
*comments
, const char *key
)
72 val
= comments_get_val(comments
, key
);
76 year
= strtol(val
, &endptr
, 10);
77 /* Looking for a four-digit number */
78 if (year
< 1000 || year
> 9999)
82 if (*endptr
== '-' || *endptr
== ' ' || *endptr
== '/') {
83 month
= strtol(endptr
+1, &endptr
, 10);
84 if (month
< 1 || month
> 12)
89 if (*endptr
== '-' || *endptr
== ' ' || *endptr
== '/') {
90 day
= strtol(endptr
+1, &endptr
, 10);
91 if (day
< 1 || day
> 31)
100 static const char *interesting
[] = {
101 "artist", "album", "title", "tracknumber", "discnumber", "genre",
102 "date", "compilation", "albumartist", "artistsort", "albumartistsort",
103 "replaygain_track_gain",
104 "replaygain_track_peak",
105 "replaygain_album_gain",
106 "replaygain_album_peak",
114 { "album_artist", "albumartist" },
115 { "album artist", "albumartist" },
116 { "disc", "discnumber" },
117 { "track", "tracknumber" },
121 static const char *fix_key(const char *key
)
125 for (i
= 0; interesting
[i
]; i
++) {
126 if (!strcasecmp(key
, interesting
[i
]))
127 return interesting
[i
];
129 for (i
= 0; key_map
[i
].old
; i
++) {
130 if (!strcasecmp(key
, key_map
[i
].old
))
131 return key_map
[i
].new;
136 int comments_add(struct growing_keyvals
*c
, const char *key
, char *val
)
138 int i
, n
= c
->count
+ 1;
146 if (!strcmp(key
, "tracknumber") || !strcmp(key
, "discnumber")) {
147 char *slash
= strchr(val
, '/');
152 /* don't add duplicates. can't use comments_get_val() */
153 for (i
= 0; i
< c
->count
; i
++) {
154 if (!strcasecmp(key
, c
->comments
[i
].key
) && !strcmp(val
, c
->comments
[i
].val
)) {
162 c
->comments
= xrenew(struct keyval
, c
->comments
, n
);
166 c
->comments
[c
->count
].key
= xstrdup(key
);
167 c
->comments
[c
->count
].val
= val
;
172 int comments_add_const(struct growing_keyvals
*c
, const char *key
, const char *val
)
174 return comments_add(c
, key
, xstrdup(val
));
177 void comments_terminate(struct growing_keyvals
*c
)
179 int alloc
= c
->count
+ 1;
181 if (alloc
> c
->alloc
) {
182 c
->comments
= xrenew(struct keyval
, c
->comments
, alloc
);
185 c
->comments
[c
->count
].key
= NULL
;
186 c
->comments
[c
->count
].val
= NULL
;