summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Listen.cxx9
-rw-r--r--src/Permission.cxx33
-rw-r--r--src/config/Block.cxx5
-rw-r--r--src/config/Block.hxx13
-rw-r--r--src/config/Data.cxx68
-rw-r--r--src/config/Data.hxx33
-rw-r--r--src/config/Global.cxx6
-rw-r--r--src/config/Param.cxx5
-rw-r--r--src/config/Param.hxx13
-rw-r--r--src/neighbor/Glue.cxx9
-rw-r--r--src/output/MultipleOutputs.cxx7
11 files changed, 85 insertions, 116 deletions
diff --git a/src/Listen.cxx b/src/Listen.cxx
index b74777127..2df05c634 100644
--- a/src/Listen.cxx
+++ b/src/Listen.cxx
@@ -88,14 +88,13 @@ listen_global_init(const ConfigData &config, ClientListener &listener)
return;
#endif
- for (const auto *param = config.GetParam(ConfigOption::BIND_TO_ADDRESS);
- param != nullptr; param = param->next) {
+ for (const auto &param : config.GetParamList(ConfigOption::BIND_TO_ADDRESS)) {
try {
- listen_add_config_param(listener, port, param);
+ listen_add_config_param(listener, port, &param);
} catch (...) {
std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)",
- param->value.c_str(),
- param->line));
+ param.value.c_str(),
+ param.line));
}
}
diff --git a/src/Permission.cxx b/src/Permission.cxx
index 0a195d854..bb67a9585 100644
--- a/src/Permission.cxx
+++ b/src/Permission.cxx
@@ -91,37 +91,32 @@ void
initPermissions(const ConfigData &config)
{
unsigned permission;
- const ConfigParam *param;
permission_default = PERMISSION_READ | PERMISSION_ADD |
PERMISSION_CONTROL | PERMISSION_ADMIN;
- param = config.GetParam(ConfigOption::PASSWORD);
-
- if (param) {
+ for (const auto &param : config.GetParamList(ConfigOption::PASSWORD)) {
permission_default = 0;
- do {
- const char *separator =
- strchr(param->value.c_str(),
- PERMISSION_PASSWORD_CHAR);
+ const char *separator = strchr(param.value.c_str(),
+ PERMISSION_PASSWORD_CHAR);
- if (separator == NULL)
- throw FormatRuntimeError("\"%c\" not found in password string "
- "\"%s\", line %i",
- PERMISSION_PASSWORD_CHAR,
- param->value.c_str(),
- param->line);
+ if (separator == NULL)
+ throw FormatRuntimeError("\"%c\" not found in password string "
+ "\"%s\", line %i",
+ PERMISSION_PASSWORD_CHAR,
+ param.value.c_str(),
+ param.line);
- std::string password(param->value.c_str(), separator);
+ std::string password(param.value.c_str(), separator);
- permission = parsePermissions(separator + 1);
+ permission = parsePermissions(separator + 1);
- permission_passwords.insert(std::make_pair(std::move(password),
- permission));
- } while ((param = param->next) != nullptr);
+ permission_passwords.insert(std::make_pair(std::move(password),
+ permission));
}
+ const ConfigParam *param;
param = config.GetParam(ConfigOption::DEFAULT_PERMS);
if (param)
diff --git a/src/config/Block.cxx b/src/config/Block.cxx
index 1c5b2c109..15bb5da95 100644
--- a/src/config/Block.cxx
+++ b/src/config/Block.cxx
@@ -78,11 +78,6 @@ BlockParam::GetBoolValue() const
return value2;
}
-ConfigBlock::~ConfigBlock()
-{
- delete next;
-}
-
const BlockParam *
ConfigBlock::GetBlockParam(const char *name) const noexcept
{
diff --git a/src/config/Block.hxx b/src/config/Block.hxx
index 380fa2277..035d8c395 100644
--- a/src/config/Block.hxx
+++ b/src/config/Block.hxx
@@ -55,12 +55,6 @@ struct BlockParam {
};
struct ConfigBlock {
- /**
- * The next #ConfigBlock with the same name. The destructor
- * deletes the whole chain.
- */
- ConfigBlock *next = nullptr;
-
int line;
std::vector<BlockParam> block_params;
@@ -74,11 +68,8 @@ struct ConfigBlock {
explicit ConfigBlock(int _line=-1)
:line(_line) {}
- ConfigBlock(const ConfigBlock &) = delete;
-
- ~ConfigBlock();
-
- ConfigBlock &operator=(const ConfigBlock &) = delete;
+ ConfigBlock(ConfigBlock &&) = default;
+ ConfigBlock &operator=(ConfigBlock &&) = default;
/**
* Determine if this is a "null" instance, i.e. an empty
diff --git a/src/config/Data.cxx b/src/config/Data.cxx
index f8518aa3d..22f8f399d 100644
--- a/src/config/Data.cxx
+++ b/src/config/Data.cxx
@@ -19,8 +19,6 @@
#include "config.h"
#include "Data.hxx"
-#include "Param.hxx"
-#include "Block.hxx"
#include "Parser.hxx"
#include "fs/AllocatedPath.hxx"
#include "util/RuntimeError.hxx"
@@ -31,35 +29,36 @@
void
ConfigData::Clear()
{
- for (auto &i : params) {
- delete i;
- i = nullptr;
- }
+ for (auto &i : params)
+ i.clear();
- for (auto &i : blocks) {
- delete i;
- i = nullptr;
- }
+ for (auto &i : blocks)
+ i.clear();
}
-gcc_nonnull_all
-static void
-Append(ConfigParam *&head, ConfigParam *p)
+template<typename T>
+gcc_pure
+static auto
+FindLast(const std::forward_list<T> &list)
{
- assert(p->next == nullptr);
-
- auto **i = &head;
- while (*i != nullptr)
- i = &(*i)->next;
+ auto i = list.before_begin();
+ while (std::next(i) != list.end())
+ ++i;
+ return i;
+}
- *i = p;
+template<typename T>
+static auto
+Append(std::forward_list<T> &list, T &&src)
+{
+ return list.emplace_after(FindLast(list), std::move(src));
}
void
ConfigData::AddParam(ConfigOption option,
std::unique_ptr<ConfigParam> param) noexcept
{
- Append(params[size_t(option)], param.release());
+ Append(GetParamList(option), std::move(*param));
}
const char *
@@ -143,39 +142,25 @@ ConfigData::GetBool(ConfigOption option, bool default_value) const
return value;
}
-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;
-}
-
-void
+ConfigBlock &
ConfigData::AddBlock(ConfigBlockOption option,
std::unique_ptr<ConfigBlock> block) noexcept
{
- Append(blocks[size_t(option)], block.release());
+ return *Append(GetBlockList(option), std::move(*block));
}
const ConfigBlock *
ConfigData::FindBlock(ConfigBlockOption option,
const char *key, const char *value) const
{
- for (const auto *block = GetBlock(option);
- block != nullptr; block = block->next) {
- const char *value2 = block->GetBlockValue(key);
+ for (const auto &block : GetBlockList(option)) {
+ const char *value2 = block.GetBlockValue(key);
if (value2 == nullptr)
throw FormatRuntimeError("block without '%s' in line %d",
- key, block->line);
+ key, block.line);
if (StringIsEqual(value2, value))
- return block;
+ return &block;
}
return nullptr;
@@ -189,8 +174,7 @@ ConfigData::MakeBlock(ConfigBlockOption option,
if (block == nullptr) {
auto new_block = std::make_unique<ConfigBlock>();
new_block->AddBlockParam(key, value);
- block = new_block.get();
- AddBlock(option, std::move(new_block));
+ block = &AddBlock(option, std::move(new_block));
}
return *block;
diff --git a/src/config/Data.hxx b/src/config/Data.hxx
index d58948489..2a0cc87e7 100644
--- a/src/config/Data.hxx
+++ b/src/config/Data.hxx
@@ -21,9 +21,12 @@
#define MPD_CONFIG_DATA_HXX
#include "Option.hxx"
+#include "Param.hxx"
+#include "Block.hxx"
#include <array>
#include <chrono>
+#include <forward_list>
#include <memory>
struct ConfigParam;
@@ -31,17 +34,26 @@ struct ConfigBlock;
class AllocatedPath;
struct ConfigData {
- std::array<ConfigParam *, std::size_t(ConfigOption::MAX)> params{{nullptr}};
- std::array<ConfigBlock *, std::size_t(ConfigBlockOption::MAX)> blocks{{nullptr}};
+ std::array<std::forward_list<ConfigParam>, std::size_t(ConfigOption::MAX)> params;
+ std::array<std::forward_list<ConfigBlock>, std::size_t(ConfigBlockOption::MAX)> blocks;
void Clear();
+ auto &GetParamList(ConfigOption option) noexcept {
+ return params[size_t(option)];
+ }
+
+ const auto &GetParamList(ConfigOption option) const noexcept {
+ return params[size_t(option)];
+ }
+
void AddParam(ConfigOption option,
std::unique_ptr<ConfigParam> param) noexcept;
gcc_pure
const ConfigParam *GetParam(ConfigOption option) const noexcept {
- return params[size_t(option)];
+ const auto &list = GetParamList(option);
+ return list.empty() ? nullptr : &list.front();
}
gcc_pure
@@ -81,12 +93,21 @@ struct ConfigData {
bool GetBool(ConfigOption option, bool default_value) const;
- void AddBlock(ConfigBlockOption option,
- std::unique_ptr<ConfigBlock> block) noexcept;
+ auto &GetBlockList(ConfigBlockOption option) noexcept {
+ return blocks[size_t(option)];
+ }
+
+ const auto &GetBlockList(ConfigBlockOption option) const noexcept {
+ return blocks[size_t(option)];
+ }
+
+ ConfigBlock &AddBlock(ConfigBlockOption option,
+ std::unique_ptr<ConfigBlock> block) noexcept;
gcc_pure
const ConfigBlock *GetBlock(ConfigBlockOption option) const noexcept {
- return blocks[size_t(option)];
+ const auto &list = GetBlockList(option);
+ return list.empty() ? nullptr : &list.front();
}
/**
diff --git a/src/config/Global.cxx b/src/config/Global.cxx
index fceb5b603..5892896b9 100644
--- a/src/config/Global.cxx
+++ b/src/config/Global.cxx
@@ -72,9 +72,9 @@ Check(const ConfigBlock &block)
void config_global_check(void)
{
- for (auto i : config_data.blocks)
- for (const auto *p = i; p != nullptr; p = p->next)
- Check(*p);
+ for (const auto &list : config_data.blocks)
+ for (const auto &block : list)
+ Check(block);
}
const char *
diff --git a/src/config/Param.cxx b/src/config/Param.cxx
index bb1962e7d..1df37285a 100644
--- a/src/config/Param.cxx
+++ b/src/config/Param.cxx
@@ -25,11 +25,6 @@
#include <stdexcept>
-ConfigParam::~ConfigParam()
-{
- delete next;
-}
-
AllocatedPath
ConfigParam::GetPath() const
{
diff --git a/src/config/Param.hxx b/src/config/Param.hxx
index e3346f7e0..d7be49a55 100644
--- a/src/config/Param.hxx
+++ b/src/config/Param.hxx
@@ -28,12 +28,6 @@
class AllocatedPath;
struct ConfigParam {
- /**
- * The next ConfigParam with the same name. The destructor
- * deletes the whole chain.
- */
- ConfigParam *next = nullptr;
-
std::string value;
int line;
@@ -46,11 +40,8 @@ struct ConfigParam {
explicit ConfigParam(V &&_value, int _line=-1) noexcept
:value(std::forward<V>(_value)), line(_line) {}
- ConfigParam(const ConfigParam &) = delete;
-
- ~ConfigParam();
-
- ConfigParam &operator=(const ConfigParam &) = delete;
+ ConfigParam(ConfigParam &&) = default;
+ ConfigParam &operator=(ConfigParam &&) = default;
/**
* Determine if this is a "null" instance, i.e. an empty
diff --git a/src/neighbor/Glue.cxx b/src/neighbor/Glue.cxx
index 5118f54a3..154e6331b 100644
--- a/src/neighbor/Glue.cxx
+++ b/src/neighbor/Glue.cxx
@@ -53,17 +53,16 @@ void
NeighborGlue::Init(const ConfigData &config,
EventLoop &loop, NeighborListener &listener)
{
- for (const auto *block = config.GetBlock(ConfigBlockOption::NEIGHBORS);
- block != nullptr; block = block->next) {
- block->SetUsed();
+ for (const auto &block : config.GetBlockList(ConfigBlockOption::NEIGHBORS)) {
+ block.SetUsed();
try {
explorers.emplace_front(CreateNeighborExplorer(loop,
listener,
- *block));
+ block));
} catch (...) {
std::throw_with_nested(FormatRuntimeError("Line %i: ",
- block->line));
+ block.line));
}
}
}
diff --git a/src/output/MultipleOutputs.cxx b/src/output/MultipleOutputs.cxx
index f84441fde..af21d2e33 100644
--- a/src/output/MultipleOutputs.cxx
+++ b/src/output/MultipleOutputs.cxx
@@ -91,13 +91,12 @@ MultipleOutputs::Configure(EventLoop &event_loop,
const ReplayGainConfig &replay_gain_config,
AudioOutputClient &client)
{
- for (const auto *param = config.GetBlock(ConfigBlockOption::AUDIO_OUTPUT);
- param != nullptr; param = param->next) {
- param->SetUsed();
+ for (const auto &block : config.GetBlockList(ConfigBlockOption::AUDIO_OUTPUT)) {
+ block.SetUsed();
auto *output = LoadOutputControl(event_loop,
replay_gain_config,
mixer_listener,
- client, *param);
+ client, block);
if (FindByName(output->GetName()) != nullptr)
throw FormatRuntimeError("output devices with identical "
"names: %s", output->GetName());