diff -r 155a6c7d3886 -r cfb7776bd6f0 src/config.c --- a/src/config.c Tue Mar 31 23:35:24 2009 +0300 +++ b/src/config.c Tue Mar 31 23:36:05 2009 +0300 @@ -1,21 +1,140 @@ #include "config.h" #include +#include -err_t config_apply (struct config_option *options, void *ctx, const char *name, char *value, struct error_info *err) +const struct config_option* config_lookup (const struct config_option *options, const char *name, struct error_info *err) { - struct config_option *option; + const struct config_option *option; // find the matching config opt for (option = options; option->name && option->type; option++) { if (strcmp(option->name, name) == 0) + return option; + } + + // not found + SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown configuration option"); + + return NULL; +} + +/** + * Parse a raw value for a CONFIG_IRC_CHAN into an irc_chan + */ +static struct irc_chan* config_parse_irc_chan (struct nexus *nexus, char *raw_value, struct error_info *err) +{ + const char *network, *channel; + struct irc_chan *chan; + + // parse required args + if ((network = strsep(&raw_value, "/")) == NULL) + JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid for CONFIG_IRC_CHAN value"); + + if ((channel = strsep(&raw_value, "/")) == NULL) + JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid for CONFIG_IRC_CHAN value"); + + // extraneous stuff? + if (raw_value) + JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "trailing data for CONFIG_IRC_CHAN value"); + + // get the channel? + if ((chan = irc_client_get_chan(nexus->client, network, channel)) == NULL) + JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "unknown network/channel name for CONFIG_IRC_CHAN value"); + + // ok + return chan; + +error: + return NULL; +} + +err_t config_parse (const struct config_option *option, struct nexus *nexus, struct config_value *value, char *raw_value, struct error_info *err) +{ + // parse the value + switch (option->type) { + case CONFIG_STRING: + // simple! + value->string = raw_value; break; + + case CONFIG_IRC_CHAN: + // parse the value + if (!(value->irc_chan = config_parse_irc_chan(nexus, raw_value, err))) + return ERROR_CODE(err); + + break; + + default: + NOT_REACHED(); } + // copy the type + value->type = option->type; + + // ok + return SUCCESS; +} + +err_t config_apply_opt (const struct config_option *option, void *ctx, const struct config_value *value, struct error_info *err) +{ + // wrong type? + if (option->type != value->type) + // XXX: info about type names + return SET_ERROR(err, ERR_CONFIG_TYPE); + + // null? + if (!value) + RETURN_SET_ERROR_STR(err, ERR_CONFIG_REQUIRED, option->name); + + // call the handler + switch (option->type) { + case CONFIG_STRING: return option->func.string(ctx, value->string, err); + case CONFIG_IRC_CHAN: return option->func.irc_chan(ctx, value->irc_chan, err); + default: NOT_REACHED(); + } +} + +err_t config_apply (const struct config_option *options, void *ctx, const char *name, const struct config_value *value, struct error_info *err) +{ + const struct config_option *option; + // no matching option found? - if (!option) - RETURN_SET_ERROR_STR(err, ERR_CONFIG_NAME, name); + if (!(option = config_lookup(options, name, err))) + return ERROR_CODE(err); + + // apply it + return config_apply_opt(option, ctx, value, err); +} - // call the handler - return option->func(ctx, value, err); +err_t config_apply_string (const struct config_option *options, void *ctx, const char *name, char *value, struct error_info *err) +{ + struct config_value conf_value = { CONFIG_STRING, { .string = value } }; + + return config_apply(options, ctx, name, &conf_value, err); } + +err_t config_apply_irc_chan (const struct config_option *options, void *ctx, const char *name, struct irc_chan *value, struct error_info *err) +{ + struct config_value conf_value = { CONFIG_STRING, { .irc_chan = value } }; + + return config_apply(options, ctx, name, &conf_value, err); +} + +err_t config_apply_raw (const struct config_option *options, struct nexus *nexus, void *ctx, const char *name, char *raw_value, struct error_info *err) +{ + const struct config_option *option; + struct config_value value; + + // no matching option found? + if (!(option = config_lookup(options, name, err))) + return ERROR_CODE(err); + + // parse it + if (config_parse(option, nexus, &value, raw_value, err)) + return ERROR_CODE(err); + + // apply it + return config_apply_opt(option, ctx, &value, err); +} +