--- 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 <string.h>
+#include <assert.h>
-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 <network> for CONFIG_IRC_CHAN value");
+
+ if ((channel = strsep(&raw_value, "/")) == NULL)
+ JUMP_SET_ERROR_STR(err, ERR_MODULE_CONF, "invalid <channel> 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);
+}
+