config/Data: use std::forward_list to manage params and blocks
This commit is contained in:
parent
fd80683ade
commit
9ff2606bb8
@ -88,14 +88,13 @@ listen_global_init(const ConfigData &config, ClientListener &listener)
|
|||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (const auto *param = config.GetParam(ConfigOption::BIND_TO_ADDRESS);
|
for (const auto ¶m : config.GetParamList(ConfigOption::BIND_TO_ADDRESS)) {
|
||||||
param != nullptr; param = param->next) {
|
|
||||||
try {
|
try {
|
||||||
listen_add_config_param(listener, port, param);
|
listen_add_config_param(listener, port, ¶m);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)",
|
std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)",
|
||||||
param->value.c_str(),
|
param.value.c_str(),
|
||||||
param->line));
|
param.line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,37 +91,32 @@ void
|
|||||||
initPermissions(const ConfigData &config)
|
initPermissions(const ConfigData &config)
|
||||||
{
|
{
|
||||||
unsigned permission;
|
unsigned permission;
|
||||||
const ConfigParam *param;
|
|
||||||
|
|
||||||
permission_default = PERMISSION_READ | PERMISSION_ADD |
|
permission_default = PERMISSION_READ | PERMISSION_ADD |
|
||||||
PERMISSION_CONTROL | PERMISSION_ADMIN;
|
PERMISSION_CONTROL | PERMISSION_ADMIN;
|
||||||
|
|
||||||
param = config.GetParam(ConfigOption::PASSWORD);
|
for (const auto ¶m : config.GetParamList(ConfigOption::PASSWORD)) {
|
||||||
|
|
||||||
if (param) {
|
|
||||||
permission_default = 0;
|
permission_default = 0;
|
||||||
|
|
||||||
do {
|
const char *separator = strchr(param.value.c_str(),
|
||||||
const char *separator =
|
|
||||||
strchr(param->value.c_str(),
|
|
||||||
PERMISSION_PASSWORD_CHAR);
|
PERMISSION_PASSWORD_CHAR);
|
||||||
|
|
||||||
if (separator == NULL)
|
if (separator == NULL)
|
||||||
throw FormatRuntimeError("\"%c\" not found in password string "
|
throw FormatRuntimeError("\"%c\" not found in password string "
|
||||||
"\"%s\", line %i",
|
"\"%s\", line %i",
|
||||||
PERMISSION_PASSWORD_CHAR,
|
PERMISSION_PASSWORD_CHAR,
|
||||||
param->value.c_str(),
|
param.value.c_str(),
|
||||||
param->line);
|
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_passwords.insert(std::make_pair(std::move(password),
|
||||||
permission));
|
permission));
|
||||||
} while ((param = param->next) != nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ConfigParam *param;
|
||||||
param = config.GetParam(ConfigOption::DEFAULT_PERMS);
|
param = config.GetParam(ConfigOption::DEFAULT_PERMS);
|
||||||
|
|
||||||
if (param)
|
if (param)
|
||||||
|
@ -78,11 +78,6 @@ BlockParam::GetBoolValue() const
|
|||||||
return value2;
|
return value2;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigBlock::~ConfigBlock()
|
|
||||||
{
|
|
||||||
delete next;
|
|
||||||
}
|
|
||||||
|
|
||||||
const BlockParam *
|
const BlockParam *
|
||||||
ConfigBlock::GetBlockParam(const char *name) const noexcept
|
ConfigBlock::GetBlockParam(const char *name) const noexcept
|
||||||
{
|
{
|
||||||
|
@ -55,12 +55,6 @@ struct BlockParam {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct ConfigBlock {
|
struct ConfigBlock {
|
||||||
/**
|
|
||||||
* The next #ConfigBlock with the same name. The destructor
|
|
||||||
* deletes the whole chain.
|
|
||||||
*/
|
|
||||||
ConfigBlock *next = nullptr;
|
|
||||||
|
|
||||||
int line;
|
int line;
|
||||||
|
|
||||||
std::vector<BlockParam> block_params;
|
std::vector<BlockParam> block_params;
|
||||||
@ -74,11 +68,8 @@ struct ConfigBlock {
|
|||||||
explicit ConfigBlock(int _line=-1)
|
explicit ConfigBlock(int _line=-1)
|
||||||
:line(_line) {}
|
:line(_line) {}
|
||||||
|
|
||||||
ConfigBlock(const ConfigBlock &) = delete;
|
ConfigBlock(ConfigBlock &&) = default;
|
||||||
|
ConfigBlock &operator=(ConfigBlock &&) = default;
|
||||||
~ConfigBlock();
|
|
||||||
|
|
||||||
ConfigBlock &operator=(const ConfigBlock &) = delete;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if this is a "null" instance, i.e. an empty
|
* Determine if this is a "null" instance, i.e. an empty
|
||||||
|
@ -19,8 +19,6 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Data.hxx"
|
#include "Data.hxx"
|
||||||
#include "Param.hxx"
|
|
||||||
#include "Block.hxx"
|
|
||||||
#include "Parser.hxx"
|
#include "Parser.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
@ -31,35 +29,36 @@
|
|||||||
void
|
void
|
||||||
ConfigData::Clear()
|
ConfigData::Clear()
|
||||||
{
|
{
|
||||||
for (auto &i : params) {
|
for (auto &i : params)
|
||||||
delete i;
|
i.clear();
|
||||||
i = nullptr;
|
|
||||||
|
for (auto &i : blocks)
|
||||||
|
i.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &i : blocks) {
|
template<typename T>
|
||||||
delete i;
|
gcc_pure
|
||||||
i = nullptr;
|
static auto
|
||||||
}
|
FindLast(const std::forward_list<T> &list)
|
||||||
}
|
|
||||||
|
|
||||||
gcc_nonnull_all
|
|
||||||
static void
|
|
||||||
Append(ConfigParam *&head, ConfigParam *p)
|
|
||||||
{
|
{
|
||||||
assert(p->next == nullptr);
|
auto i = list.before_begin();
|
||||||
|
while (std::next(i) != list.end())
|
||||||
|
++i;
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
auto **i = &head;
|
template<typename T>
|
||||||
while (*i != nullptr)
|
static auto
|
||||||
i = &(*i)->next;
|
Append(std::forward_list<T> &list, T &&src)
|
||||||
|
{
|
||||||
*i = p;
|
return list.emplace_after(FindLast(list), std::move(src));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ConfigData::AddParam(ConfigOption option,
|
ConfigData::AddParam(ConfigOption option,
|
||||||
std::unique_ptr<ConfigParam> param) noexcept
|
std::unique_ptr<ConfigParam> param) noexcept
|
||||||
{
|
{
|
||||||
Append(params[size_t(option)], param.release());
|
Append(GetParamList(option), std::move(*param));
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
@ -143,39 +142,25 @@ ConfigData::GetBool(ConfigOption option, bool default_value) const
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_nonnull_all
|
ConfigBlock &
|
||||||
static void
|
|
||||||
Append(ConfigBlock *&head, ConfigBlock *p)
|
|
||||||
{
|
|
||||||
assert(p->next == nullptr);
|
|
||||||
|
|
||||||
auto **i = &head;
|
|
||||||
while (*i != nullptr)
|
|
||||||
i = &(*i)->next;
|
|
||||||
|
|
||||||
*i = p;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
ConfigData::AddBlock(ConfigBlockOption option,
|
ConfigData::AddBlock(ConfigBlockOption option,
|
||||||
std::unique_ptr<ConfigBlock> block) noexcept
|
std::unique_ptr<ConfigBlock> block) noexcept
|
||||||
{
|
{
|
||||||
Append(blocks[size_t(option)], block.release());
|
return *Append(GetBlockList(option), std::move(*block));
|
||||||
}
|
}
|
||||||
|
|
||||||
const ConfigBlock *
|
const ConfigBlock *
|
||||||
ConfigData::FindBlock(ConfigBlockOption option,
|
ConfigData::FindBlock(ConfigBlockOption option,
|
||||||
const char *key, const char *value) const
|
const char *key, const char *value) const
|
||||||
{
|
{
|
||||||
for (const auto *block = GetBlock(option);
|
for (const auto &block : GetBlockList(option)) {
|
||||||
block != nullptr; block = block->next) {
|
const char *value2 = block.GetBlockValue(key);
|
||||||
const char *value2 = block->GetBlockValue(key);
|
|
||||||
if (value2 == nullptr)
|
if (value2 == nullptr)
|
||||||
throw FormatRuntimeError("block without '%s' in line %d",
|
throw FormatRuntimeError("block without '%s' in line %d",
|
||||||
key, block->line);
|
key, block.line);
|
||||||
|
|
||||||
if (StringIsEqual(value2, value))
|
if (StringIsEqual(value2, value))
|
||||||
return block;
|
return █
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -189,8 +174,7 @@ ConfigData::MakeBlock(ConfigBlockOption option,
|
|||||||
if (block == nullptr) {
|
if (block == nullptr) {
|
||||||
auto new_block = std::make_unique<ConfigBlock>();
|
auto new_block = std::make_unique<ConfigBlock>();
|
||||||
new_block->AddBlockParam(key, value);
|
new_block->AddBlockParam(key, value);
|
||||||
block = new_block.get();
|
block = &AddBlock(option, std::move(new_block));
|
||||||
AddBlock(option, std::move(new_block));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return *block;
|
return *block;
|
||||||
|
@ -21,9 +21,12 @@
|
|||||||
#define MPD_CONFIG_DATA_HXX
|
#define MPD_CONFIG_DATA_HXX
|
||||||
|
|
||||||
#include "Option.hxx"
|
#include "Option.hxx"
|
||||||
|
#include "Param.hxx"
|
||||||
|
#include "Block.hxx"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <forward_list>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
struct ConfigParam;
|
struct ConfigParam;
|
||||||
@ -31,17 +34,26 @@ struct ConfigBlock;
|
|||||||
class AllocatedPath;
|
class AllocatedPath;
|
||||||
|
|
||||||
struct ConfigData {
|
struct ConfigData {
|
||||||
std::array<ConfigParam *, std::size_t(ConfigOption::MAX)> params{{nullptr}};
|
std::array<std::forward_list<ConfigParam>, std::size_t(ConfigOption::MAX)> params;
|
||||||
std::array<ConfigBlock *, std::size_t(ConfigBlockOption::MAX)> blocks{{nullptr}};
|
std::array<std::forward_list<ConfigBlock>, std::size_t(ConfigBlockOption::MAX)> blocks;
|
||||||
|
|
||||||
void Clear();
|
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,
|
void AddParam(ConfigOption option,
|
||||||
std::unique_ptr<ConfigParam> param) noexcept;
|
std::unique_ptr<ConfigParam> param) noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const ConfigParam *GetParam(ConfigOption option) const noexcept {
|
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
|
gcc_pure
|
||||||
@ -81,12 +93,21 @@ struct ConfigData {
|
|||||||
|
|
||||||
bool GetBool(ConfigOption option, bool default_value) const;
|
bool GetBool(ConfigOption option, bool default_value) const;
|
||||||
|
|
||||||
void AddBlock(ConfigBlockOption option,
|
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;
|
std::unique_ptr<ConfigBlock> block) noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
const ConfigBlock *GetBlock(ConfigBlockOption option) const noexcept {
|
const ConfigBlock *GetBlock(ConfigBlockOption option) const noexcept {
|
||||||
return blocks[size_t(option)];
|
const auto &list = GetBlockList(option);
|
||||||
|
return list.empty() ? nullptr : &list.front();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,9 +72,9 @@ Check(const ConfigBlock &block)
|
|||||||
|
|
||||||
void config_global_check(void)
|
void config_global_check(void)
|
||||||
{
|
{
|
||||||
for (auto i : config_data.blocks)
|
for (const auto &list : config_data.blocks)
|
||||||
for (const auto *p = i; p != nullptr; p = p->next)
|
for (const auto &block : list)
|
||||||
Check(*p);
|
Check(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
const char *
|
||||||
|
@ -25,11 +25,6 @@
|
|||||||
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
ConfigParam::~ConfigParam()
|
|
||||||
{
|
|
||||||
delete next;
|
|
||||||
}
|
|
||||||
|
|
||||||
AllocatedPath
|
AllocatedPath
|
||||||
ConfigParam::GetPath() const
|
ConfigParam::GetPath() const
|
||||||
{
|
{
|
||||||
|
@ -28,12 +28,6 @@
|
|||||||
class AllocatedPath;
|
class AllocatedPath;
|
||||||
|
|
||||||
struct ConfigParam {
|
struct ConfigParam {
|
||||||
/**
|
|
||||||
* The next ConfigParam with the same name. The destructor
|
|
||||||
* deletes the whole chain.
|
|
||||||
*/
|
|
||||||
ConfigParam *next = nullptr;
|
|
||||||
|
|
||||||
std::string value;
|
std::string value;
|
||||||
|
|
||||||
int line;
|
int line;
|
||||||
@ -46,11 +40,8 @@ struct ConfigParam {
|
|||||||
explicit ConfigParam(V &&_value, int _line=-1) noexcept
|
explicit ConfigParam(V &&_value, int _line=-1) noexcept
|
||||||
:value(std::forward<V>(_value)), line(_line) {}
|
:value(std::forward<V>(_value)), line(_line) {}
|
||||||
|
|
||||||
ConfigParam(const ConfigParam &) = delete;
|
ConfigParam(ConfigParam &&) = default;
|
||||||
|
ConfigParam &operator=(ConfigParam &&) = default;
|
||||||
~ConfigParam();
|
|
||||||
|
|
||||||
ConfigParam &operator=(const ConfigParam &) = delete;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if this is a "null" instance, i.e. an empty
|
* Determine if this is a "null" instance, i.e. an empty
|
||||||
|
@ -53,17 +53,16 @@ void
|
|||||||
NeighborGlue::Init(const ConfigData &config,
|
NeighborGlue::Init(const ConfigData &config,
|
||||||
EventLoop &loop, NeighborListener &listener)
|
EventLoop &loop, NeighborListener &listener)
|
||||||
{
|
{
|
||||||
for (const auto *block = config.GetBlock(ConfigBlockOption::NEIGHBORS);
|
for (const auto &block : config.GetBlockList(ConfigBlockOption::NEIGHBORS)) {
|
||||||
block != nullptr; block = block->next) {
|
block.SetUsed();
|
||||||
block->SetUsed();
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
explorers.emplace_front(CreateNeighborExplorer(loop,
|
explorers.emplace_front(CreateNeighborExplorer(loop,
|
||||||
listener,
|
listener,
|
||||||
*block));
|
block));
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::throw_with_nested(FormatRuntimeError("Line %i: ",
|
std::throw_with_nested(FormatRuntimeError("Line %i: ",
|
||||||
block->line));
|
block.line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,13 +91,12 @@ MultipleOutputs::Configure(EventLoop &event_loop,
|
|||||||
const ReplayGainConfig &replay_gain_config,
|
const ReplayGainConfig &replay_gain_config,
|
||||||
AudioOutputClient &client)
|
AudioOutputClient &client)
|
||||||
{
|
{
|
||||||
for (const auto *param = config.GetBlock(ConfigBlockOption::AUDIO_OUTPUT);
|
for (const auto &block : config.GetBlockList(ConfigBlockOption::AUDIO_OUTPUT)) {
|
||||||
param != nullptr; param = param->next) {
|
block.SetUsed();
|
||||||
param->SetUsed();
|
|
||||||
auto *output = LoadOutputControl(event_loop,
|
auto *output = LoadOutputControl(event_loop,
|
||||||
replay_gain_config,
|
replay_gain_config,
|
||||||
mixer_listener,
|
mixer_listener,
|
||||||
client, *param);
|
client, block);
|
||||||
if (FindByName(output->GetName()) != nullptr)
|
if (FindByName(output->GetName()) != nullptr)
|
||||||
throw FormatRuntimeError("output devices with identical "
|
throw FormatRuntimeError("output devices with identical "
|
||||||
"names: %s", output->GetName());
|
"names: %s", output->GetName());
|
||||||
|
Loading…
Reference in New Issue
Block a user