aboutsummaryrefslogtreecommitdiffstats
path: root/src/config
diff options
context:
space:
mode:
Diffstat (limited to 'src/config')
-rw-r--r--src/config/Block.cxx97
-rw-r--r--src/config/Block.hxx72
-rw-r--r--src/config/ConfigFile.cxx139
-rw-r--r--src/config/ConfigGlobal.cxx38
-rw-r--r--src/config/ConfigGlobal.hxx9
-rw-r--r--src/config/ConfigOption.hxx19
-rw-r--r--src/config/ConfigTemplates.cxx157
-rw-r--r--src/config/ConfigTemplates.hxx4
-rw-r--r--src/config/Data.cxx6
-rw-r--r--src/config/Data.hxx2
-rw-r--r--src/config/Param.cxx94
-rw-r--r--src/config/Param.hxx39
12 files changed, 406 insertions, 270 deletions
diff --git a/src/config/Block.cxx b/src/config/Block.cxx
index ba26c560f..a74903b10 100644
--- a/src/config/Block.cxx
+++ b/src/config/Block.cxx
@@ -20,8 +20,12 @@
#include "config.h"
#include "Block.hxx"
#include "ConfigParser.hxx"
+#include "ConfigPath.hxx"
#include "system/FatalError.hxx"
+#include "fs/AllocatedPath.hxx"
+#include "util/Error.hxx"
+#include <assert.h>
#include <stdlib.h>
int
@@ -57,3 +61,96 @@ BlockParam::GetBoolValue() const
return value2;
}
+
+ConfigBlock::~ConfigBlock()
+{
+ delete next;
+}
+
+const BlockParam *
+ConfigBlock::GetBlockParam(const char *name) const
+{
+ for (const auto &i : block_params) {
+ if (i.name == name) {
+ i.used = true;
+ return &i;
+ }
+ }
+
+ return nullptr;
+}
+
+const char *
+ConfigBlock::GetBlockValue(const char *name, const char *default_value) const
+{
+ const BlockParam *bp = GetBlockParam(name);
+ if (bp == nullptr)
+ return default_value;
+
+ return bp->value.c_str();
+}
+
+AllocatedPath
+ConfigBlock::GetBlockPath(const char *name, const char *default_value,
+ Error &error) const
+{
+ assert(!error.IsDefined());
+
+ int line2 = line;
+ const char *s;
+
+ const BlockParam *bp = GetBlockParam(name);
+ if (bp != nullptr) {
+ line2 = bp->line;
+ s = bp->value.c_str();
+ } else {
+ if (default_value == nullptr)
+ return AllocatedPath::Null();
+
+ s = default_value;
+ }
+
+ AllocatedPath path = ParsePath(s, error);
+ if (gcc_unlikely(path.IsNull()))
+ error.FormatPrefix("Invalid path in \"%s\" at line %i: ",
+ name, line2);
+
+ return path;
+}
+
+AllocatedPath
+ConfigBlock::GetBlockPath(const char *name, Error &error) const
+{
+ return GetBlockPath(name, nullptr, error);
+}
+
+int
+ConfigBlock::GetBlockValue(const char *name, int default_value) const
+{
+ const BlockParam *bp = GetBlockParam(name);
+ if (bp == nullptr)
+ return default_value;
+
+ return bp->GetIntValue();
+}
+
+unsigned
+ConfigBlock::GetBlockValue(const char *name, unsigned default_value) const
+{
+ const BlockParam *bp = GetBlockParam(name);
+ if (bp == nullptr)
+ return default_value;
+
+ return bp->GetUnsignedValue();
+}
+
+gcc_pure
+bool
+ConfigBlock::GetBlockValue(const char *name, bool default_value) const
+{
+ const BlockParam *bp = GetBlockParam(name);
+ if (bp == nullptr)
+ return default_value;
+
+ return bp->GetBoolValue();
+}
diff --git a/src/config/Block.hxx b/src/config/Block.hxx
index c2194eff9..23b064695 100644
--- a/src/config/Block.hxx
+++ b/src/config/Block.hxx
@@ -21,9 +21,14 @@
#define MPD_CONFIG_BLOCK_HXX
#include "check.h"
+#include "Param.hxx"
#include "Compiler.h"
#include <string>
+#include <vector>
+
+class Error;
+class AllocatedPath;
struct BlockParam {
std::string name;
@@ -50,4 +55,71 @@ struct BlockParam {
bool GetBoolValue() const;
};
+struct ConfigBlock {
+ /**
+ * The next #ConfigBlock with the same name. The destructor
+ * deletes the whole chain.
+ */
+ ConfigBlock *next;
+
+ int line;
+
+ std::vector<BlockParam> block_params;
+
+ /**
+ * This flag is false when nobody has queried the value of
+ * this option yet.
+ */
+ bool used;
+
+ explicit ConfigBlock(int _line=-1)
+ :next(nullptr), line(_line), used(false) {}
+
+ ConfigBlock(const ConfigBlock &) = delete;
+
+ ~ConfigBlock();
+
+ ConfigBlock &operator=(const ConfigBlock &) = delete;
+
+ /**
+ * Determine if this is a "null" instance, i.e. an empty
+ * object that was synthesized and not loaded from a
+ * configuration file.
+ */
+ bool IsNull() const {
+ return line < 0;
+ }
+
+ gcc_nonnull_all
+ void AddBlockParam(const char *_name, const char *_value,
+ int _line=-1) {
+ block_params.emplace_back(_name, _value, _line);
+ }
+
+ gcc_nonnull_all gcc_pure
+ const BlockParam *GetBlockParam(const char *_name) const;
+
+ gcc_pure
+ const char *GetBlockValue(const char *name,
+ const char *default_value=nullptr) const;
+
+ /**
+ * Same as config_get_path(), but looks up the setting in the
+ * specified block.
+ */
+ AllocatedPath GetBlockPath(const char *name, const char *default_value,
+ Error &error) const;
+
+ AllocatedPath GetBlockPath(const char *name, Error &error) const;
+
+ gcc_pure
+ int GetBlockValue(const char *name, int default_value) const;
+
+ gcc_pure
+ unsigned GetBlockValue(const char *name, unsigned default_value) const;
+
+ gcc_pure
+ bool GetBlockValue(const char *name, bool default_value) const;
+};
+
#endif
diff --git a/src/config/ConfigFile.cxx b/src/config/ConfigFile.cxx
index 38945f8ec..a5ad020d4 100644
--- a/src/config/ConfigFile.cxx
+++ b/src/config/ConfigFile.cxx
@@ -21,6 +21,7 @@
#include "ConfigFile.hxx"
#include "Data.hxx"
#include "Param.hxx"
+#include "Block.hxx"
#include "ConfigTemplates.hxx"
#include "util/Tokenizer.hxx"
#include "util/StringUtil.hxx"
@@ -38,7 +39,7 @@ static constexpr char CONF_COMMENT = '#';
static constexpr Domain config_file_domain("config_file");
static bool
-config_read_name_value(struct config_param *param, char *input, unsigned line,
+config_read_name_value(ConfigBlock &block, char *input, unsigned line,
Error &error)
{
Tokenizer tokenizer(input);
@@ -65,7 +66,7 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
return false;
}
- const BlockParam *bp = param->GetBlockParam(name);
+ const BlockParam *bp = block.GetBlockParam(name);
if (bp != nullptr) {
error.Format(config_file_domain,
"\"%s\" is duplicate, first defined on line %i",
@@ -73,14 +74,14 @@ config_read_name_value(struct config_param *param, char *input, unsigned line,
return false;
}
- param->AddBlockParam(name, value, line);
+ block.AddBlockParam(name, value, line);
return true;
}
-static struct config_param *
+static ConfigBlock *
config_read_block(BufferedReader &reader, Error &error)
{
- struct config_param *ret = new config_param(reader.GetLineNumber());
+ auto *ret = new ConfigBlock(reader.GetLineNumber());
while (true) {
char *line = reader.ReadLine();
@@ -115,7 +116,7 @@ config_read_block(BufferedReader &reader, Error &error)
/* parse name and value */
- if (!config_read_name_value(ret, line, reader.GetLineNumber(),
+ if (!config_read_name_value(*ret, line, reader.GetLineNumber(),
error)) {
assert(*line != 0);
delete ret;
@@ -127,6 +128,64 @@ config_read_block(BufferedReader &reader, Error &error)
gcc_nonnull_all
static void
+Append(ConfigBlock *&head, ConfigBlock *p)
+{
+ assert(p->next == nullptr);
+
+ auto **i = &head;
+ while (*i != nullptr)
+ i = &(*i)->next;
+
+ *i = p;
+}
+
+static bool
+ReadConfigBlock(ConfigData &config_data, BufferedReader &reader,
+ const char *name, ConfigOption o,
+ Tokenizer &tokenizer,
+ Error &error)
+{
+ const unsigned i = unsigned(o);
+ const ConfigTemplate &option = config_block_templates[i];
+ ConfigBlock *&head = config_data.blocks[i];
+
+ if (head != nullptr && !option.repeatable) {
+ ConfigBlock *block = head;
+ error.Format(config_file_domain,
+ "config parameter \"%s\" is first defined "
+ "on line %d and redefined on line %u\n",
+ name, block->line,
+ reader.GetLineNumber());
+ return false;
+ }
+
+ /* now parse the block or the value */
+
+ if (tokenizer.CurrentChar() != '{') {
+ error.Format(config_file_domain,
+ "line %u: '{' expected",
+ reader.GetLineNumber());
+ return false;
+ }
+
+ char *line = StripLeft(tokenizer.Rest() + 1);
+ if (*line != 0 && *line != CONF_COMMENT) {
+ error.Format(config_file_domain,
+ "line %u: Unknown tokens after '{'",
+ reader.GetLineNumber());
+ return false;
+ }
+
+ auto *param = config_read_block(reader, error);
+ if (param == nullptr)
+ return false;
+
+ Append(head, param);
+ return true;
+}
+
+gcc_nonnull_all
+static void
Append(config_param *&head, config_param *p)
{
assert(p->next == nullptr);
@@ -145,7 +204,7 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader,
Error &error)
{
const unsigned i = unsigned(o);
- const ConfigTemplate &option = config_templates[i];
+ const ConfigTemplate &option = config_param_templates[i];
config_param *&head = config_data.params[i];
if (head != nullptr && !option.repeatable) {
@@ -160,57 +219,28 @@ ReadConfigParam(ConfigData &config_data, BufferedReader &reader,
/* now parse the block or the value */
- struct config_param *param;
- if (option.block) {
- /* it's a block, call config_read_block() */
-
- if (tokenizer.CurrentChar() != '{') {
- error.Format(config_file_domain,
- "line %u: '{' expected",
- reader.GetLineNumber());
- return false;
- }
-
- char *line = StripLeft(tokenizer.Rest() + 1);
- if (*line != 0 && *line != CONF_COMMENT) {
+ const char *value = tokenizer.NextString(error);
+ if (value == nullptr) {
+ if (tokenizer.IsEnd())
error.Format(config_file_domain,
- "line %u: Unknown tokens after '{'",
+ "line %u: Value missing",
reader.GetLineNumber());
- return false;
- }
+ else
+ error.FormatPrefix("line %u: ",
+ reader.GetLineNumber());
- param = config_read_block(reader, error);
- if (param == nullptr) {
- return false;
- }
- } else {
- /* a string value */
-
- const char *value = tokenizer.NextString(error);
- if (value == nullptr) {
- if (tokenizer.IsEnd())
- error.Format(config_file_domain,
- "line %u: Value missing",
- reader.GetLineNumber());
- else
- error.FormatPrefix("line %u: ",
- reader.GetLineNumber());
-
- return false;
- }
-
- if (!tokenizer.IsEnd() &&
- tokenizer.CurrentChar() != CONF_COMMENT) {
- error.Format(config_file_domain,
- "line %u: Unknown tokens after value",
- reader.GetLineNumber());
- return false;
- }
+ return false;
+ }
- param = new config_param(value,
- reader.GetLineNumber());
+ if (!tokenizer.IsEnd() &&
+ tokenizer.CurrentChar() != CONF_COMMENT) {
+ error.Format(config_file_domain,
+ "line %u: Unknown tokens after value",
+ reader.GetLineNumber());
+ return false;
}
+ auto *param = new config_param(value, reader.GetLineNumber());
Append(head, param);
return true;
}
@@ -242,10 +272,15 @@ ReadConfigFile(ConfigData &config_data, BufferedReader &reader, Error &error)
"repeatable" flag */
const ConfigOption o = ParseConfigOptionName(name);
+ ConfigBlockOption bo;
if (o != ConfigOption::MAX) {
if (!ReadConfigParam(config_data, reader, name, o,
tokenizer, error))
return false;
+ } else if ((bo = ParseConfigBlockOptionName(name)) != ConfigBlockOption::MAX) {
+ if (!ReadConfigBlock(config_data, reader, name, o,
+ tokenizer, error))
+ return false;
} else {
error.Format(config_file_domain,
"unrecognized parameter in config file at "
diff --git a/src/config/ConfigGlobal.cxx b/src/config/ConfigGlobal.cxx
index 5c04ea93e..192baffec 100644
--- a/src/config/ConfigGlobal.cxx
+++ b/src/config/ConfigGlobal.cxx
@@ -22,6 +22,7 @@
#include "ConfigParser.hxx"
#include "Data.hxx"
#include "Param.hxx"
+#include "Block.hxx"
#include "ConfigFile.hxx"
#include "ConfigPath.hxx"
#include "ConfigError.hxx"
@@ -51,15 +52,15 @@ ReadConfigFile(Path path, Error &error)
}
static void
-Check(const config_param *param)
+Check(const ConfigBlock &block)
{
- if (!param->used)
- /* this whole config_param was not queried at all -
+ if (!block.used)
+ /* this whole block was not queried at all -
the feature might be disabled at compile time?
Silently ignore it here. */
return;
- for (const auto &i : param->block_params) {
+ for (const auto &i : block.block_params) {
if (!i.used)
FormatWarning(config_domain,
"option '%s' on line %i was not recognized",
@@ -69,9 +70,9 @@ Check(const config_param *param)
void config_global_check(void)
{
- for (auto i : config_data.params)
- for (const config_param *p = i; p != nullptr; p = p->next)
- Check(p);
+ for (auto i : config_data.blocks)
+ for (const auto *p = i; p != nullptr; p = p->next)
+ Check(*p);
}
const config_param *
@@ -83,18 +84,27 @@ config_get_param(ConfigOption option)
return param;
}
-const config_param *
-config_find_block(ConfigOption option, const char *key, const char *value)
+const ConfigBlock *
+config_get_block(ConfigBlockOption option)
+{
+ ConfigBlock *block = config_data.blocks[unsigned(option)];
+ if (block != nullptr)
+ block->used = true;
+ return block;
+}
+
+const ConfigBlock *
+config_find_block(ConfigBlockOption option, const char *key, const char *value)
{
- for (const config_param *param = config_get_param(option);
- param != nullptr; param = param->next) {
- const char *value2 = param->GetBlockValue(key);
+ for (const auto *block = config_get_block(option);
+ block != nullptr; block = block->next) {
+ const char *value2 = block->GetBlockValue(key);
if (value2 == nullptr)
FormatFatalError("block without '%s' name in line %d",
- key, param->line);
+ key, block->line);
if (strcmp(value2, value) == 0)
- return param;
+ return block;
}
return nullptr;
diff --git a/src/config/ConfigGlobal.hxx b/src/config/ConfigGlobal.hxx
index ac7d5c4fd..3c6a938a6 100644
--- a/src/config/ConfigGlobal.hxx
+++ b/src/config/ConfigGlobal.hxx
@@ -27,6 +27,7 @@ class Error;
class Path;
class AllocatedPath;
struct config_param;
+struct ConfigBlock;
void config_global_init(void);
void config_global_finish(void);
@@ -44,6 +45,10 @@ gcc_pure
const config_param *
config_get_param(enum ConfigOption option);
+gcc_pure
+const ConfigBlock *
+config_get_block(enum ConfigBlockOption option);
+
/**
* Find a block with a matching attribute.
*
@@ -52,8 +57,8 @@ config_get_param(enum ConfigOption option);
* @param value the expected attribute value
*/
gcc_pure
-const config_param *
-config_find_block(ConfigOption option, const char *key, const char *value);
+const ConfigBlock *
+config_find_block(ConfigBlockOption option, const char *key, const char *value);
/* Note on gcc_pure: Some of the functions declared pure are not
really pure in strict sense. They have side effect such that they
diff --git a/src/config/ConfigOption.hxx b/src/config/ConfigOption.hxx
index c3f4c9aad..8cc0d42d5 100644
--- a/src/config/ConfigOption.hxx
+++ b/src/config/ConfigOption.hxx
@@ -49,7 +49,6 @@ enum class ConfigOption {
ZEROCONF_ENABLED,
PASSWORD,
DEFAULT_PERMS,
- AUDIO_OUTPUT,
AUDIO_OUTPUT_FORMAT,
MIXER_TYPE,
REPLAYGAIN,
@@ -73,15 +72,20 @@ enum class ConfigOption {
ID3V1_ENCODING,
METADATA_TO_USE,
SAVE_ABSOLUTE_PATHS,
- DECODER,
- INPUT,
GAPLESS_MP3_PLAYBACK,
- PLAYLIST_PLUGIN,
AUTO_UPDATE,
AUTO_UPDATE_DEPTH,
DESPOTIFY_USER,
DESPOTIFY_PASSWORD,
DESPOTIFY_HIGH_BITRATE,
+ MAX
+};
+
+enum class ConfigBlockOption {
+ AUDIO_OUTPUT,
+ DECODER,
+ INPUT,
+ PLAYLIST_PLUGIN,
AUDIO_FILTER,
DATABASE,
NEIGHBORS,
@@ -99,4 +103,11 @@ gcc_pure
enum ConfigOption
ParseConfigOptionName(const char *name);
+/**
+ * @return #ConfigOption::MAX if not found
+ */
+gcc_pure
+enum ConfigBlockOption
+ParseConfigBlockOptionName(const char *name);
+
#endif
diff --git a/src/config/ConfigTemplates.cxx b/src/config/ConfigTemplates.cxx
index 8f01d4104..1ceef9119 100644
--- a/src/config/ConfigTemplates.cxx
+++ b/src/config/ConfigTemplates.cxx
@@ -23,76 +23,105 @@
#include <string.h>
-const ConfigTemplate config_templates[] = {
- { "music_directory", false, false },
- { "playlist_directory", false, false },
- { "follow_inside_symlinks", false, false },
- { "follow_outside_symlinks", false, false },
- { "db_file", false, false },
- { "sticker_file", false, false },
- { "log_file", false, false },
- { "pid_file", false, false },
- { "state_file", false, false },
- { "state_file_interval", false, false },
- { "restore_paused", false, false },
- { "user", false, false },
- { "group", false, false },
- { "bind_to_address", true, false },
- { "port", false, false },
- { "log_level", false, false },
- { "zeroconf_name", false, false },
- { "zeroconf_enabled", false, false },
- { "password", true, false },
- { "default_permissions", false, false },
- { "audio_output", true, true },
- { "audio_output_format", false, false },
- { "mixer_type", false, false },
- { "replaygain", false, false },
- { "replaygain_preamp", false, false },
- { "replaygain_missing_preamp", false, false },
- { "replaygain_limit", false, false },
- { "volume_normalization", false, false },
- { "samplerate_converter", false, false },
- { "audio_buffer_size", false, false },
- { "buffer_before_play", false, false },
- { "http_proxy_host", false, false },
- { "http_proxy_port", false, false },
- { "http_proxy_user", false, false },
- { "http_proxy_password", false, false },
- { "connection_timeout", false, false },
- { "max_connections", false, false },
- { "max_playlist_length", false, false },
- { "max_command_list_size", false, false },
- { "max_output_buffer_size", false, false },
- { "filesystem_charset", false, false },
- { "id3v1_encoding", false, false },
- { "metadata_to_use", false, false },
- { "save_absolute_paths_in_playlists", false, false },
- { "decoder", true, true },
- { "input", true, true },
- { "gapless_mp3_playback", false, false },
- { "playlist_plugin", true, true },
- { "auto_update", false, false },
- { "auto_update_depth", false, false },
- { "despotify_user", false, false },
- { "despotify_password", false, false},
- { "despotify_high_bitrate", false, false },
- { "filter", true, true },
- { "database", false, true },
- { "neighbors", true, true },
+const ConfigTemplate config_param_templates[] = {
+ { "music_directory", false },
+ { "playlist_directory", false },
+ { "follow_inside_symlinks", false },
+ { "follow_outside_symlinks", false },
+ { "db_file", false },
+ { "sticker_file", false },
+ { "log_file", false },
+ { "pid_file", false },
+ { "state_file", false },
+ { "state_file_interval", false },
+ { "restore_paused", false },
+ { "user", false },
+ { "group", false },
+ { "bind_to_address", true },
+ { "port", false },
+ { "log_level", false },
+ { "zeroconf_name", false },
+ { "zeroconf_enabled", false },
+ { "password", true },
+ { "default_permissions", false },
+ { "audio_output_format", false },
+ { "mixer_type", false },
+ { "replaygain", false },
+ { "replaygain_preamp", false },
+ { "replaygain_missing_preamp", false },
+ { "replaygain_limit", false },
+ { "volume_normalization", false },
+ { "samplerate_converter", false },
+ { "audio_buffer_size", false },
+ { "buffer_before_play", false },
+ { "http_proxy_host", false },
+ { "http_proxy_port", false },
+ { "http_proxy_user", false },
+ { "http_proxy_password", false },
+ { "connection_timeout", false },
+ { "max_connections", false },
+ { "max_playlist_length", false },
+ { "max_command_list_size", false },
+ { "max_output_buffer_size", false },
+ { "filesystem_charset", false },
+ { "id3v1_encoding", false },
+ { "metadata_to_use", false },
+ { "save_absolute_paths_in_playlists", false },
+ { "gapless_mp3_playback", false },
+ { "auto_update", false },
+ { "auto_update_depth", false },
+ { "despotify_user", false },
+ { "despotify_password", false },
+ { "despotify_high_bitrate", false },
};
-static constexpr unsigned n_config_templates = ARRAY_SIZE(config_templates);
+static constexpr unsigned n_config_param_templates =
+ ARRAY_SIZE(config_param_templates);
-static_assert(n_config_templates == unsigned(ConfigOption::MAX),
- "Wrong number of config_templates");
+static_assert(n_config_param_templates == unsigned(ConfigOption::MAX),
+ "Wrong number of config_param_templates");
+
+const ConfigTemplate config_block_templates[] = {
+ { "audio_output", true },
+ { "decoder", true },
+ { "input", true },
+ { "playlist_plugin", true },
+ { "filter", true },
+ { "database", false },
+ { "neighbors", true },
+};
+
+static constexpr unsigned n_config_block_templates =
+ ARRAY_SIZE(config_block_templates);
+
+static_assert(n_config_block_templates == unsigned(ConfigBlockOption::MAX),
+ "Wrong number of config_block_templates");
+
+gcc_pure
+static inline unsigned
+ParseConfigTemplateName(const ConfigTemplate templates[], unsigned count,
+ const char *name)
+{
+ unsigned i = 0;
+ for (; i < count; ++i)
+ if (strcmp(templates[i].name, name) == 0)
+ break;
+
+ return i;
+}
ConfigOption
ParseConfigOptionName(const char *name)
{
- for (unsigned i = 0; i < n_config_templates; ++i)
- if (strcmp(config_templates[i].name, name) == 0)
- return ConfigOption(i);
+ return ConfigOption(ParseConfigTemplateName(config_param_templates,
+ n_config_param_templates,
+ name));
+}
- return ConfigOption::MAX;
+ConfigBlockOption
+ParseConfigBlockOptionName(const char *name)
+{
+ return ConfigBlockOption(ParseConfigTemplateName(config_block_templates,
+ n_config_block_templates,
+ name));
}
diff --git a/src/config/ConfigTemplates.hxx b/src/config/ConfigTemplates.hxx
index f034773e3..1aa6c6e8d 100644
--- a/src/config/ConfigTemplates.hxx
+++ b/src/config/ConfigTemplates.hxx
@@ -23,9 +23,9 @@
struct ConfigTemplate {
const char *const name;
const bool repeatable;
- const bool block;
};
-extern const ConfigTemplate config_templates[];
+extern const ConfigTemplate config_param_templates[];
+extern const ConfigTemplate config_block_templates[];
#endif
diff --git a/src/config/Data.cxx b/src/config/Data.cxx
index 4aae9f7dc..52521e31a 100644
--- a/src/config/Data.cxx
+++ b/src/config/Data.cxx
@@ -20,6 +20,7 @@
#include "config.h"
#include "Data.hxx"
#include "Param.hxx"
+#include "Block.hxx"
void
ConfigData::Clear()
@@ -28,4 +29,9 @@ ConfigData::Clear()
delete i;
i = nullptr;
}
+
+ for (auto &i : blocks) {
+ delete i;
+ i = nullptr;
+ }
}
diff --git a/src/config/Data.hxx b/src/config/Data.hxx
index 56e7d2553..6036c49e6 100644
--- a/src/config/Data.hxx
+++ b/src/config/Data.hxx
@@ -25,9 +25,11 @@
#include <array>
struct config_param;
+struct ConfigBlock;
struct ConfigData {
std::array<config_param *, std::size_t(ConfigOption::MAX)> params;
+ std::array<ConfigBlock *, std::size_t(ConfigBlockOption::MAX)> blocks;
void Clear();
};
diff --git a/src/config/Param.cxx b/src/config/Param.cxx
index 376f50ee7..bfd9743d2 100644
--- a/src/config/Param.cxx
+++ b/src/config/Param.cxx
@@ -19,12 +19,6 @@
#include "config.h"
#include "Param.hxx"
-#include "ConfigPath.hxx"
-#include "util/Error.hxx"
-#include "fs/AllocatedPath.hxx"
-
-#include <assert.h>
-#include <stdlib.h>
config_param::config_param(const char *_value, int _line)
:next(nullptr), value(_value), line(_line), used(false) {}
@@ -33,91 +27,3 @@ config_param::~config_param()
{
delete next;
}
-
-const BlockParam *
-config_param::GetBlockParam(const char *name) const
-{
- for (const auto &i : block_params) {
- if (i.name == name) {
- i.used = true;
- return &i;
- }
- }
-
- return nullptr;
-}
-
-const char *
-config_param::GetBlockValue(const char *name, const char *default_value) const
-{
- const BlockParam *bp = GetBlockParam(name);
- if (bp == nullptr)
- return default_value;
-
- return bp->value.c_str();
-}
-
-AllocatedPath
-config_param::GetBlockPath(const char *name, const char *default_value,
- Error &error) const
-{
- assert(!error.IsDefined());
-
- int line2 = line;
- const char *s;
-
- const BlockParam *bp = GetBlockParam(name);
- if (bp != nullptr) {
- line2 = bp->line;
- s = bp->value.c_str();
- } else {
- if (default_value == nullptr)
- return AllocatedPath::Null();
-
- s = default_value;
- }
-
- AllocatedPath path = ParsePath(s, error);
- if (gcc_unlikely(path.IsNull()))
- error.FormatPrefix("Invalid path in \"%s\" at line %i: ",
- name, line2);
-
- return path;
-}
-
-AllocatedPath
-config_param::GetBlockPath(const char *name, Error &error) const
-{
- return GetBlockPath(name, nullptr, error);
-}
-
-int
-config_param::GetBlockValue(const char *name, int default_value) const
-{
- const BlockParam *bp = GetBlockParam(name);
- if (bp == nullptr)
- return default_value;
-
- return bp->GetIntValue();
-}
-
-unsigned
-config_param::GetBlockValue(const char *name, unsigned default_value) const
-{
- const BlockParam *bp = GetBlockParam(name);
- if (bp == nullptr)
- return default_value;
-
- return bp->GetUnsignedValue();
-}
-
-gcc_pure
-bool
-config_param::GetBlockValue(const char *name, bool default_value) const
-{
- const BlockParam *bp = GetBlockParam(name);
- if (bp == nullptr)
- return default_value;
-
- return bp->GetBoolValue();
-}
diff --git a/src/config/Param.hxx b/src/config/Param.hxx
index a3cd3f83a..e6a039c2a 100644
--- a/src/config/Param.hxx
+++ b/src/config/Param.hxx
@@ -20,14 +20,10 @@
#ifndef MPD_CONFIG_PARAM_HXX
#define MPD_CONFIG_PARAM_HXX
-#include "Block.hxx"
+#include "check.h"
#include "Compiler.h"
#include <string>
-#include <vector>
-
-class AllocatedPath;
-class Error;
struct config_param {
/**
@@ -40,8 +36,6 @@ struct config_param {
int line;
- std::vector<BlockParam> block_params;
-
/**
* This flag is false when nobody has queried the value of
* this option yet.
@@ -68,37 +62,6 @@ struct config_param {
bool IsNull() const {
return line < 0;
}
-
- gcc_nonnull_all
- void AddBlockParam(const char *_name, const char *_value,
- int _line=-1) {
- block_params.emplace_back(_name, _value, _line);
- }
-
- gcc_nonnull_all gcc_pure
- const BlockParam *GetBlockParam(const char *_name) const;
-
- gcc_pure
- const char *GetBlockValue(const char *name,
- const char *default_value=nullptr) const;
-
- /**
- * Same as config_get_path(), but looks up the setting in the
- * specified block.
- */
- AllocatedPath GetBlockPath(const char *name, const char *default_value,
- Error &error) const;
-
- AllocatedPath GetBlockPath(const char *name, Error &error) const;
-
- gcc_pure
- int GetBlockValue(const char *name, int default_value) const;
-
- gcc_pure
- unsigned GetBlockValue(const char *name, unsigned default_value) const;
-
- gcc_pure
- bool GetBlockValue(const char *name, bool default_value) const;
};
#endif