boost/asio/impl/config.ipp
//
// impl/config.ipp
// ~~~~~~~~~~~~~~~
//
// Copyright (c) 2003-2024 Christopher M. Kohlhoff (chris at kohlhoff dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_ASIO_IMPL_CONFIG_IPP
#define BOOST_ASIO_IMPL_CONFIG_IPP
#if defined(_MSC_VER) && (_MSC_VER >= 1200)
# pragma once
#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
#include <boost/asio/config.hpp>
#include <boost/asio/detail/concurrency_hint.hpp>
#include <cctype>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <utility>
#include <boost/asio/detail/push_options.hpp>
namespace boost {
namespace asio {
config_service::config_service(execution_context& ctx)
: detail::execution_context_service_base<config_service>(ctx)
{
}
void config_service::shutdown()
{
}
const char* config_service::get_value(const char* /*section*/,
const char* /*key*/, char* /*value*/, std::size_t /*value_len*/) const
{
return nullptr;
}
namespace detail {
class config_from_concurrency_hint_service : public config_service
{
public:
explicit config_from_concurrency_hint_service(
execution_context& ctx, int concurrency_hint)
: config_service(ctx),
concurrency_hint_(concurrency_hint)
{
}
const char* get_value(const char* section, const char* key,
char* value, std::size_t value_len) const override
{
if (std::strcmp(section, "scheduler") == 0)
{
if (std::strcmp(key, "concurrency_hint") == 0)
{
std::snprintf(value, value_len, "%d",
BOOST_ASIO_CONCURRENCY_HINT_IS_SPECIAL(concurrency_hint_)
? 1 : concurrency_hint_);
return value;
}
else if (std::strcmp(key, "locking") == 0)
{
return BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
SCHEDULER, concurrency_hint_) ? "1" : "0";
}
}
else if (std::strcmp(section, "reactor") == 0)
{
if (std::strcmp(key, "io_locking") == 0)
{
return BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
REACTOR_IO, concurrency_hint_) ? "1" : "0";
}
else if (std::strcmp(key, "registration_locking") == 0)
{
return BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
REACTOR_REGISTRATION, concurrency_hint_) ? "1" : "0";
}
}
return nullptr;
}
private:
int concurrency_hint_;
};
} // namespace detail
config_from_concurrency_hint::config_from_concurrency_hint()
: concurrency_hint_(BOOST_ASIO_CONCURRENCY_HINT_DEFAULT)
{
}
void config_from_concurrency_hint::make(execution_context& ctx) const
{
(void)make_service<detail::config_from_concurrency_hint_service>(ctx,
concurrency_hint_ == 1
? BOOST_ASIO_CONCURRENCY_HINT_1 : concurrency_hint_);
}
namespace detail {
class config_from_string_service : public config_service
{
public:
config_from_string_service(execution_context& ctx,
std::string s, std::string prefix)
: config_service(ctx),
string_(static_cast<std::string&&>(s)),
prefix_(static_cast<std::string&&>(prefix))
{
enum
{
expecting_key,
key,
expecting_equals,
expecting_value,
value,
expecting_eol
} state = expecting_key;
std::pair<const char*, const char*> entry{};
for (char& c : string_)
{
switch (state)
{
case expecting_key:
switch (c)
{
case ' ': case '\t': case '\n':
break;
case '#':
state = expecting_eol;
break;
default:
entry.first = &c;
state = key;
break;
}
break;
case key:
switch (c)
{
case ' ': case '\t':
c = 0;
state = expecting_equals;
break;
case '=':
c = 0;
state = expecting_value;
break;
case '\n':
entry.first = nullptr;
state = expecting_key;
break;
case '#':
entry.first = nullptr;
state = expecting_eol;
break;
default:
break;
}
break;
case expecting_equals:
switch (c)
{
case ' ': case '\t':
break;
case '=':
state = expecting_value;
break;
case '\n':
entry.first = nullptr;
state = expecting_key;
break;
default:
entry.first = nullptr;
state = expecting_eol;
break;
}
break;
case expecting_value:
switch (c)
{
case ' ': case '\t':
break;
case '\n':
entry.first = nullptr;
state = expecting_key;
break;
case '#':
entry.first = nullptr;
state = expecting_eol;
break;
default:
entry.second = &c;
state = value;
break;
}
break;
case value:
switch (c)
{
case '\n':
c = 0;
entries_.push_back(entry);
entry.first = entry.second = nullptr;
state = expecting_key;
break;
case '#':
c = 0;
entries_.push_back(entry);
entry.first = entry.second = nullptr;
state = expecting_eol;
break;
default:
break;
}
break;
case expecting_eol:
switch (c)
{
case '\n':
state = expecting_key;
break;
default:
break;
}
break;
}
}
if (entry.first && entry.second)
entries_.push_back(entry);
}
const char* get_value(const char* section, const char* key,
char* /*value*/, std::size_t /*value_len*/) const override
{
std::string entry_key;
entry_key.reserve(prefix_.length() + 1
+ std::strlen(section) + 1
+ std::strlen(key) + 1);
entry_key.append(prefix_);
if (!entry_key.empty())
entry_key.append(".");
entry_key.append(section);
entry_key.append(".");
entry_key.append(key);
for (const std::pair<const char*, const char*>& entry : entries_)
if (entry_key == entry.first)
return entry.second;
return nullptr;
}
private:
std::string string_;
std::string prefix_;
std::vector<std::pair<const char*, const char*>> entries_;
};
} // namespace detail
void config_from_string::make(execution_context& ctx) const
{
(void)make_service<detail::config_from_string_service>(ctx, string_, prefix_);
}
namespace detail {
#if defined(BOOST_ASIO_MSVC)
# pragma warning (push)
# pragma warning (disable:4996) // suppress unsafe warning for std::getenv
#endif // defined(BOOST_ASIO_MSVC)
class config_from_env_service : public config_service
{
public:
explicit config_from_env_service(
execution_context& ctx, std::string prefix)
: config_service(ctx),
prefix_(static_cast<std::string&&>(prefix))
{
}
const char* get_value(const char* section, const char* key,
char* /*value*/, std::size_t /*value_len*/) const override
{
std::string env_var;
env_var.reserve(prefix_.length() + 1
+ std::strlen(section) + 1
+ std::strlen(key) + 1);
env_var.append(prefix_);
if (!env_var.empty())
env_var.append("_");
env_var.append(section);
env_var.append("_");
env_var.append(key);
for (char& c : env_var)
c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
return std::getenv(env_var.c_str());
}
private:
std::string prefix_;
};
#if defined(BOOST_ASIO_MSVC)
# pragma warning (pop)
#endif // defined(BOOST_ASIO_MSVC)
} // namespace detail
config_from_env::config_from_env()
: prefix_("asio")
{
}
void config_from_env::make(execution_context& ctx) const
{
(void)make_service<detail::config_from_env_service>(ctx, prefix_);
}
} // namespace asio
} // namespace boost
#include <boost/asio/detail/pop_options.hpp>
#endif // BOOST_ASIO_IMPL_CONFIG_IPP