Johannes Weißl
2011-03-10 11:47:55 UTC
e.g. %-20{artist} instead of %-20a
Suggested by Timo:
http://sourceforge.net/mailarchive/message.php?msg_id=1970124
---
format_print.c | 86 ++++++++++++++++++++++++++++++++++++++-----------------
format_print.h | 15 ++++++----
options.c | 2 +-
ui_curses.c | 53 +++++++++++++++++++---------------
ui_curses.h | 2 +
5 files changed, 100 insertions(+), 58 deletions(-)
diff --git a/format_print.c b/format_print.c
index 88c3a1f..3487d10 100644
--- a/format_print.c
+++ b/format_print.c
@@ -180,6 +180,11 @@ static void print_str(char *buf, int *idx, const char *str)
*idx = d;
}
+static inline int strnequal(const char *a, const char *b, size_t b_len)
+{
+ return a && (strlen(a) == b_len) && (memcmp(a, b, b_len) == 0);
+}
+
static void print(char *str, const char *format, const struct format_option *fopts)
{
/* format and str indices */
@@ -187,6 +192,8 @@ static void print(char *str, const char *format, const struct format_option *fop
while (format[s]) {
const struct format_option *fo;
+ int long_len = 0;
+ const char *long_begin = NULL;
uchar u;
u = u_get_char(format, &s);
@@ -220,8 +227,19 @@ static void print(char *str, const char *format, const struct format_option *fop
width += u - '0';
u = u_get_char(format, &s);
}
- for (fo = fopts; fo->ch; fo++) {
- if (fo->ch == u) {
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ BUG_ON(u == 0);
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
+ for (fo = fopts; fo->type; fo++) {
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
int type = fo->type;
if (fo->empty) {
@@ -259,7 +277,8 @@ int format_print(char *str, int str_width, const char *format, const struct form
while (format[s]) {
const struct format_option *fo;
- int nlen;
+ int nlen, long_len = 0;
+ const char *long_begin = NULL;
uchar u;
u = u_get_char(format, &s);
@@ -287,9 +306,20 @@ int format_print(char *str, int str_width, const char *format, const struct form
nlen += u - '0';
u = u_get_char(format, &s);
}
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ BUG_ON(u == 0);
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
for (fo = fopts; ; fo++) {
- BUG_ON(fo->ch == 0);
- if (fo->ch == u) {
+ BUG_ON(fo->type == 0);
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
int type = fo->type;
int l = 0;
@@ -397,8 +427,7 @@ int format_print(char *str, int str_width, const char *format, const struct form
return 0;
}
-/* FIXME: compare with struct format_option[] */
-int format_valid(const char *format)
+int format_valid(const char *format, const struct format_option *fopts)
{
int s = 0;
@@ -407,7 +436,9 @@ int format_valid(const char *format)
u = u_get_char(format, &s);
if (u == '%') {
- int pad_zero = 0;
+ int pad_zero = 0, long_len = 0;
+ const struct format_option *fo;
+ const char *long_begin = NULL;
u = u_get_char(format, &s);
if (u == '%' || u == '=')
@@ -420,26 +451,27 @@ int format_valid(const char *format)
}
while (isdigit(u))
u = u_get_char(format, &s);
- switch (u) {
- case 'A':
- case 'a':
- case 'l':
- case 't':
- case 'd':
- case 'g':
- case 'c':
- case 'f':
- case 'F':
- if (pad_zero)
- return 0;
- break;
- case 'D':
- case 'n':
- case 'y':
- break;
- default:
- return 0;
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ if (!u)
+ return 0;
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
+ for (fo = fopts; fo->type; fo++) {
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
+ if (pad_zero && !fo->pad_zero)
+ return 0;
+ break;
+ }
}
+ if (! fo->type)
+ return 0;
}
}
return 1;
diff --git a/format_print.h b/format_print.h
index 08db08b..fb73fad 100644
--- a/format_print.h
+++ b/format_print.h
@@ -11,8 +11,11 @@ struct format_option {
};
/* set to 1 if you want to disable printing */
unsigned int empty : 1;
- enum { FO_STR, FO_INT, FO_TIME } type;
+ /* set to 1 if zero padding is allowed */
+ unsigned int pad_zero : 1;
+ enum { FO_STR = 1, FO_INT, FO_TIME } type;
char ch;
+ const char *str;
};
/* gcc < 4.6 and icc < 12.0 can't properly initialize anonymous unions */
@@ -23,12 +26,12 @@ struct format_option {
#define UNION_INIT(f, v) .f = v
#endif
-#define DEF_FO_STR(c) { UNION_INIT(fo_str, NULL), .type = FO_STR, .ch = c }
-#define DEF_FO_INT(c) { UNION_INIT(fo_int, 0), .type = FO_INT, .ch = c }
-#define DEF_FO_TIME(c) { UNION_INIT(fo_time, 0), .type = FO_TIME, .ch = c }
-#define DEF_FO_END { UNION_INIT(fo_str, NULL), .type = 0, .ch = 0 }
+#define DEF_FO_STR(c, s, z) { UNION_INIT(fo_str, NULL), .type = FO_STR, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_INT(c, s, z) { UNION_INIT(fo_int, 0), .type = FO_INT, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_TIME(c, s, z) { UNION_INIT(fo_time, 0), .type = FO_TIME, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_END { .type = 0 }
int format_print(char *str, int width, const char *format, const struct format_option *fopts);
-int format_valid(const char *format);
+int format_valid(const char *format, const struct format_option *fopts);
#endif
diff --git a/options.c b/options.c
index 0febb78..007a5b9 100644
--- a/options.c
+++ b/options.c
@@ -844,7 +844,7 @@ static void set_format(unsigned int id, const char *buf)
{
char **fmtp = id_to_fmt(id);
- if (!format_valid(buf)) {
+ if (!track_format_valid(buf)) {
error_msg("invalid format string");
return;
}
diff --git a/ui_curses.c b/ui_curses.c
index 0df5a03..c60d8a6 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -221,18 +221,18 @@ enum {
};
static struct format_option track_fopts[NR_TFS + 1] = {
- DEF_FO_STR('A'),
- DEF_FO_STR('a'),
- DEF_FO_STR('l'),
- DEF_FO_INT('D'),
- DEF_FO_INT('n'),
- DEF_FO_STR('t'),
- DEF_FO_STR('y'),
- DEF_FO_STR('g'),
- DEF_FO_STR('c'),
- DEF_FO_TIME('d'),
- DEF_FO_STR('f'),
- DEF_FO_STR('F'),
+ DEF_FO_STR('A', "albumartist", 0),
+ DEF_FO_STR('a', "artist", 0),
+ DEF_FO_STR('l', "album", 0),
+ DEF_FO_INT('D', "discnumber", 1),
+ DEF_FO_INT('n', "tracknumber", 1),
+ DEF_FO_STR('t', "title", 0),
+ DEF_FO_STR('y', "date", 1),
+ DEF_FO_STR('g', "genre", 0),
+ DEF_FO_STR('c', "comment", 0),
+ DEF_FO_TIME('d', "duration", 0),
+ DEF_FO_STR('f', "path", 0),
+ DEF_FO_STR('F', "filename", 0),
DEF_FO_END
};
@@ -253,21 +253,26 @@ enum {
};
static struct format_option status_fopts[NR_SFS + 1] = {
- DEF_FO_STR('s'),
- DEF_FO_TIME('p'),
- DEF_FO_TIME('d'),
- DEF_FO_TIME('t'),
- DEF_FO_INT('v'),
- DEF_FO_INT('l'),
- DEF_FO_INT('r'),
- DEF_FO_INT('b'),
- DEF_FO_STR('R'),
- DEF_FO_STR('C'),
- DEF_FO_STR('S'),
- DEF_FO_STR('L'),
+ DEF_FO_STR('s', NULL, 0),
+ DEF_FO_TIME('p', NULL, 0),
+ DEF_FO_TIME('d', NULL, 0),
+ DEF_FO_TIME('t', NULL, 0),
+ DEF_FO_INT('v', NULL, 0),
+ DEF_FO_INT('l', NULL, 0),
+ DEF_FO_INT('r', NULL, 0),
+ DEF_FO_INT('b', NULL, 0),
+ DEF_FO_STR('R', NULL, 0),
+ DEF_FO_STR('C', NULL, 0),
+ DEF_FO_STR('S', NULL, 0),
+ DEF_FO_STR('L', NULL, 0),
DEF_FO_END
};
+int track_format_valid(const char *format)
+{
+ return format_valid(format, track_fopts);
+}
+
static void utf8_encode(const char *buffer)
{
static iconv_t cd = (iconv_t)-1;
diff --git a/ui_curses.h b/ui_curses.h
index 70cf3ed..44b0ef5 100644
--- a/ui_curses.h
+++ b/ui_curses.h
@@ -61,4 +61,6 @@ void enter_command_mode(void);
void enter_search_mode(void);
void enter_search_backward_mode(void);
+int track_format_valid(const char *format);
+
#endif
Suggested by Timo:
http://sourceforge.net/mailarchive/message.php?msg_id=1970124
---
format_print.c | 86 ++++++++++++++++++++++++++++++++++++++-----------------
format_print.h | 15 ++++++----
options.c | 2 +-
ui_curses.c | 53 +++++++++++++++++++---------------
ui_curses.h | 2 +
5 files changed, 100 insertions(+), 58 deletions(-)
diff --git a/format_print.c b/format_print.c
index 88c3a1f..3487d10 100644
--- a/format_print.c
+++ b/format_print.c
@@ -180,6 +180,11 @@ static void print_str(char *buf, int *idx, const char *str)
*idx = d;
}
+static inline int strnequal(const char *a, const char *b, size_t b_len)
+{
+ return a && (strlen(a) == b_len) && (memcmp(a, b, b_len) == 0);
+}
+
static void print(char *str, const char *format, const struct format_option *fopts)
{
/* format and str indices */
@@ -187,6 +192,8 @@ static void print(char *str, const char *format, const struct format_option *fop
while (format[s]) {
const struct format_option *fo;
+ int long_len = 0;
+ const char *long_begin = NULL;
uchar u;
u = u_get_char(format, &s);
@@ -220,8 +227,19 @@ static void print(char *str, const char *format, const struct format_option *fop
width += u - '0';
u = u_get_char(format, &s);
}
- for (fo = fopts; fo->ch; fo++) {
- if (fo->ch == u) {
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ BUG_ON(u == 0);
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
+ for (fo = fopts; fo->type; fo++) {
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
int type = fo->type;
if (fo->empty) {
@@ -259,7 +277,8 @@ int format_print(char *str, int str_width, const char *format, const struct form
while (format[s]) {
const struct format_option *fo;
- int nlen;
+ int nlen, long_len = 0;
+ const char *long_begin = NULL;
uchar u;
u = u_get_char(format, &s);
@@ -287,9 +306,20 @@ int format_print(char *str, int str_width, const char *format, const struct form
nlen += u - '0';
u = u_get_char(format, &s);
}
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ BUG_ON(u == 0);
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
for (fo = fopts; ; fo++) {
- BUG_ON(fo->ch == 0);
- if (fo->ch == u) {
+ BUG_ON(fo->type == 0);
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
int type = fo->type;
int l = 0;
@@ -397,8 +427,7 @@ int format_print(char *str, int str_width, const char *format, const struct form
return 0;
}
-/* FIXME: compare with struct format_option[] */
-int format_valid(const char *format)
+int format_valid(const char *format, const struct format_option *fopts)
{
int s = 0;
@@ -407,7 +436,9 @@ int format_valid(const char *format)
u = u_get_char(format, &s);
if (u == '%') {
- int pad_zero = 0;
+ int pad_zero = 0, long_len = 0;
+ const struct format_option *fo;
+ const char *long_begin = NULL;
u = u_get_char(format, &s);
if (u == '%' || u == '=')
@@ -420,26 +451,27 @@ int format_valid(const char *format)
}
while (isdigit(u))
u = u_get_char(format, &s);
- switch (u) {
- case 'A':
- case 'a':
- case 'l':
- case 't':
- case 'd':
- case 'g':
- case 'c':
- case 'f':
- case 'F':
- if (pad_zero)
- return 0;
- break;
- case 'D':
- case 'n':
- case 'y':
- break;
- default:
- return 0;
+ if (u == '{') {
+ long_begin = format + s;
+ while (1) {
+ u = u_get_char(format, &s);
+ if (!u)
+ return 0;
+ if (u == '}')
+ break;
+ long_len++;
+ }
+ }
+ for (fo = fopts; fo->type; fo++) {
+ if (long_len ? strnequal(fo->str, long_begin, long_len)
+ : (fo->ch == u)) {
+ if (pad_zero && !fo->pad_zero)
+ return 0;
+ break;
+ }
}
+ if (! fo->type)
+ return 0;
}
}
return 1;
diff --git a/format_print.h b/format_print.h
index 08db08b..fb73fad 100644
--- a/format_print.h
+++ b/format_print.h
@@ -11,8 +11,11 @@ struct format_option {
};
/* set to 1 if you want to disable printing */
unsigned int empty : 1;
- enum { FO_STR, FO_INT, FO_TIME } type;
+ /* set to 1 if zero padding is allowed */
+ unsigned int pad_zero : 1;
+ enum { FO_STR = 1, FO_INT, FO_TIME } type;
char ch;
+ const char *str;
};
/* gcc < 4.6 and icc < 12.0 can't properly initialize anonymous unions */
@@ -23,12 +26,12 @@ struct format_option {
#define UNION_INIT(f, v) .f = v
#endif
-#define DEF_FO_STR(c) { UNION_INIT(fo_str, NULL), .type = FO_STR, .ch = c }
-#define DEF_FO_INT(c) { UNION_INIT(fo_int, 0), .type = FO_INT, .ch = c }
-#define DEF_FO_TIME(c) { UNION_INIT(fo_time, 0), .type = FO_TIME, .ch = c }
-#define DEF_FO_END { UNION_INIT(fo_str, NULL), .type = 0, .ch = 0 }
+#define DEF_FO_STR(c, s, z) { UNION_INIT(fo_str, NULL), .type = FO_STR, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_INT(c, s, z) { UNION_INIT(fo_int, 0), .type = FO_INT, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_TIME(c, s, z) { UNION_INIT(fo_time, 0), .type = FO_TIME, .pad_zero = z, .ch = c, .str = s }
+#define DEF_FO_END { .type = 0 }
int format_print(char *str, int width, const char *format, const struct format_option *fopts);
-int format_valid(const char *format);
+int format_valid(const char *format, const struct format_option *fopts);
#endif
diff --git a/options.c b/options.c
index 0febb78..007a5b9 100644
--- a/options.c
+++ b/options.c
@@ -844,7 +844,7 @@ static void set_format(unsigned int id, const char *buf)
{
char **fmtp = id_to_fmt(id);
- if (!format_valid(buf)) {
+ if (!track_format_valid(buf)) {
error_msg("invalid format string");
return;
}
diff --git a/ui_curses.c b/ui_curses.c
index 0df5a03..c60d8a6 100644
--- a/ui_curses.c
+++ b/ui_curses.c
@@ -221,18 +221,18 @@ enum {
};
static struct format_option track_fopts[NR_TFS + 1] = {
- DEF_FO_STR('A'),
- DEF_FO_STR('a'),
- DEF_FO_STR('l'),
- DEF_FO_INT('D'),
- DEF_FO_INT('n'),
- DEF_FO_STR('t'),
- DEF_FO_STR('y'),
- DEF_FO_STR('g'),
- DEF_FO_STR('c'),
- DEF_FO_TIME('d'),
- DEF_FO_STR('f'),
- DEF_FO_STR('F'),
+ DEF_FO_STR('A', "albumartist", 0),
+ DEF_FO_STR('a', "artist", 0),
+ DEF_FO_STR('l', "album", 0),
+ DEF_FO_INT('D', "discnumber", 1),
+ DEF_FO_INT('n', "tracknumber", 1),
+ DEF_FO_STR('t', "title", 0),
+ DEF_FO_STR('y', "date", 1),
+ DEF_FO_STR('g', "genre", 0),
+ DEF_FO_STR('c', "comment", 0),
+ DEF_FO_TIME('d', "duration", 0),
+ DEF_FO_STR('f', "path", 0),
+ DEF_FO_STR('F', "filename", 0),
DEF_FO_END
};
@@ -253,21 +253,26 @@ enum {
};
static struct format_option status_fopts[NR_SFS + 1] = {
- DEF_FO_STR('s'),
- DEF_FO_TIME('p'),
- DEF_FO_TIME('d'),
- DEF_FO_TIME('t'),
- DEF_FO_INT('v'),
- DEF_FO_INT('l'),
- DEF_FO_INT('r'),
- DEF_FO_INT('b'),
- DEF_FO_STR('R'),
- DEF_FO_STR('C'),
- DEF_FO_STR('S'),
- DEF_FO_STR('L'),
+ DEF_FO_STR('s', NULL, 0),
+ DEF_FO_TIME('p', NULL, 0),
+ DEF_FO_TIME('d', NULL, 0),
+ DEF_FO_TIME('t', NULL, 0),
+ DEF_FO_INT('v', NULL, 0),
+ DEF_FO_INT('l', NULL, 0),
+ DEF_FO_INT('r', NULL, 0),
+ DEF_FO_INT('b', NULL, 0),
+ DEF_FO_STR('R', NULL, 0),
+ DEF_FO_STR('C', NULL, 0),
+ DEF_FO_STR('S', NULL, 0),
+ DEF_FO_STR('L', NULL, 0),
DEF_FO_END
};
+int track_format_valid(const char *format)
+{
+ return format_valid(format, track_fopts);
+}
+
static void utf8_encode(const char *buffer)
{
static iconv_t cd = (iconv_t)-1;
diff --git a/ui_curses.h b/ui_curses.h
index 70cf3ed..44b0ef5 100644
--- a/ui_curses.h
+++ b/ui_curses.h
@@ -61,4 +61,6 @@ void enter_command_mode(void);
void enter_search_mode(void);
void enter_search_backward_mode(void);
+int track_format_valid(const char *format);
+
#endif
--
1.7.4.1
1.7.4.1