1 /*****************************************************************************
2 * This file is part of gfxprim library. *
4 * Gfxprim is free software; you can redistribute it and/or *
5 * modify it under the terms of the GNU Lesser General Public *
6 * License as published by the Free Software Foundation; either *
7 * version 2.1 of the License, or (at your option) any later version. *
9 * Gfxprim is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
12 * Lesser General Public License for more details. *
14 * You should have received a copy of the GNU Lesser General Public *
15 * License along with gfxprim; if not, write to the Free Software *
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, *
17 * Boston, MA 02110-1301 USA *
19 * Copyright (C) 2009-2011 Cyril Hrubis <metan@ucw.cz> *
21 *****************************************************************************/
32 static const char *param_type_names
[] = {
40 const char *param_type_name(enum param_type type
)
42 if (type
> PARAM_ENUM
)
45 return param_type_names
[type
];
48 static const char *param_type_names_padd
[] = {
56 static void padd(unsigned int n
)
63 static void print_enum(const char *enum_table
[])
69 for (i
= 0; enum_table
[i
] != NULL
; i
++)
70 if (enum_table
[i
+1] == NULL
)
71 printf("%s]", enum_table
[i
]);
73 printf("%s | ", enum_table
[i
]);
76 void param_describe(const struct param
*param_desc
, const char *prefix
)
78 unsigned int i
, len
= 0, l
;
80 for (i
= 0; param_desc
[i
].name
!= NULL
; i
++) {
81 l
= strlen(param_desc
[i
].name
);
87 for (i
= 0; param_desc
[i
].name
!= NULL
; i
++) {
88 printf("%s%s", prefix
, param_desc
[i
].name
);
89 padd(len
- strlen(param_desc
[i
].name
));
90 printf(" : %s", param_type_names_padd
[param_desc
[i
].type
]);
91 printf(" - %s", param_desc
[i
].desc
);
93 if (param_desc
[i
].type
== PARAM_ENUM
)
94 print_enum(param_desc
[i
].enum_table
);
100 static unsigned int count_params(const char *params
)
102 unsigned int ret
= 1, i
;
105 for (i
= 0; params
[i
] != '\0'; i
++) {
107 if (params
[i
] == ':' && prev
!= ':')
116 static void split_params(char *params
, char **names
)
118 unsigned int i
, n
= 0;
121 for (i
= 0; params
[i
] != '\0'; i
++) {
123 if (params
[i
] != ':' && prev
== ':')
124 names
[n
++] = ¶ms
[i
];
128 if (params
[i
] == ':')
133 static void do_split(char *param
, char **value
)
139 for (i
= 0; param
[i
] != '\0'; i
++) {
141 if (param
[i
] == '=' || isspace(param
[i
])) {
143 *value
= ¶m
[i
+1];
148 static void split_values(char **names
, char **values
, unsigned int n
)
152 for (i
= 0; i
< n
; i
++)
153 do_split(names
[i
], &values
[i
]);
156 int param_pos(char *names
[], const char *name
, unsigned int start
, unsigned int n
)
160 for (i
= start
; i
< n
; i
++)
161 if (!strcasecmp(names
[i
], name
))
167 int set_int(int *res
, char *val
)
173 l
= strtol(val
, &end
, 0);
186 static char *bool_false
[] = {
193 static char *bool_true
[] = {
200 int set_bool(int *res
, char *val
)
204 for (i
= 0; bool_false
[i
] != NULL
; i
++)
205 if (!strcasecmp(val
, bool_false
[i
])) {
210 for (i
= 0; bool_true
[i
] != NULL
; i
++)
211 if (!strcasecmp(val
, bool_true
[i
])) {
219 int set_float(float *res
, char *val
)
225 d
= strtod(val
, &end
);
238 int set_enum(int *res
, char *val
, const char *enums
[])
242 for (i
= 0; enums
[i
] != NULL
; i
++)
243 if (!strcasecmp(enums
[i
], val
)) {
251 int set_str(char **res
, char *val
)
257 #define CALL_ERR_CALLBACK(error, p, value, private) do { \
261 if ((error_ret = error(p, value, private))) \
265 int param_parse(const char *params
, const struct param
*param_desc
, void *priv
,
266 int (*err
)(const struct param
*self
, const char *val
, void *priv
), ...)
273 if (params
== NULL
|| *params
== '\0')
276 par
= strdup(params
);
279 fprintf(stderr
, "Malloc failed :(\n");
283 n
= count_params(params
);
289 memset(flags
, 0, sizeof(flags
));
291 split_params(par
, names
);
292 split_values(names
, values
, n
);
296 for (i
= 0; param_desc
[i
].name
!= NULL
; i
++) {
297 void *arg
= va_arg(va
, void*);
300 while ((pos
= param_pos(names
, param_desc
[i
].name
, pos
, n
)) >= 0) {
302 if (values
[pos
] == NULL
|| *values
[pos
] == '\0') {
303 CALL_ERR_CALLBACK(err
, ¶m_desc
[i
], "", priv
);
309 switch (param_desc
[i
].type
) {
311 if ((ret
= set_bool(arg
, values
[pos
]))) {
312 CALL_ERR_CALLBACK(err
, ¶m_desc
[i
],
318 if ((ret
= set_int(arg
, values
[pos
]))) {
319 CALL_ERR_CALLBACK(err
, ¶m_desc
[i
],
325 if ((ret
= set_float(arg
, values
[pos
]))) {
326 CALL_ERR_CALLBACK(err
, ¶m_desc
[i
],
332 if ((ret
= set_str(arg
, values
[pos
]))) {
333 CALL_ERR_CALLBACK(err
, ¶m_desc
[i
],
339 if ((ret
= set_enum(arg
, values
[pos
],
340 param_desc
[i
].enum_table
))) {
341 CALL_ERR_CALLBACK(err
, ¶m_desc
[i
],
348 if (param_desc
[i
].check
!= NULL
)
349 if ((ret
= param_desc
[i
].check(¶m_desc
[i
], arg
, flags
[i
]))) {
350 CALL_ERR_CALLBACK(err
, ¶m_desc
[i
],
358 for (i
= 0; i
< n
; i
++) {
360 /* unknown parameter passed */
362 CALL_ERR_CALLBACK(err
, NULL
, names
[i
], priv
);
366 /* parameter redefined */