// // impl/config.ipp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2025 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 ASIO_IMPL_CONFIG_IPP #define ASIO_IMPL_CONFIG_IPP #if defined(_MSC_VER) && (_MSC_VER >= 1200) # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) #include "asio/config.hpp" #include "asio/detail/concurrency_hint.hpp" #include #include #include #include #include #include #include "asio/detail/push_options.hpp" namespace asio { config_service::config_service(execution_context& ctx) : detail::execution_context_service_base(ctx) { } void config_service::shutdown() { } const char* config_service::get_value(const char* /*section*/, const char* /*key_name*/, 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_name, char* value, std::size_t value_len) const override { if (std::strcmp(section, "scheduler") == 0) { if (std::strcmp(key_name, "concurrency_hint") == 0) { if (ASIO_CONCURRENCY_HINT_IS_SPECIAL(concurrency_hint_)) { return !ASIO_CONCURRENCY_HINT_IS_LOCKING( SCHEDULER, concurrency_hint_) || !ASIO_CONCURRENCY_HINT_IS_LOCKING( REACTOR_IO, concurrency_hint_) ? "1" : "-1"; } else { std::snprintf(value, value_len, "%d", concurrency_hint_); return value; } } else if (std::strcmp(key_name, "locking") == 0) { return ASIO_CONCURRENCY_HINT_IS_LOCKING( SCHEDULER, concurrency_hint_) ? "1" : "0"; } } else if (std::strcmp(section, "reactor") == 0) { if (std::strcmp(key_name, "io_locking") == 0) { return ASIO_CONCURRENCY_HINT_IS_LOCKING( REACTOR_IO, concurrency_hint_) ? "1" : "0"; } else if (std::strcmp(key_name, "registration_locking") == 0) { return 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_(ASIO_CONCURRENCY_HINT_DEFAULT) { } void config_from_concurrency_hint::make(execution_context& ctx) const { (void)make_service(ctx, concurrency_hint_ == 1 ? 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(s)), prefix_(static_cast(prefix)) { enum { expecting_key_name, key_name, expecting_equals, expecting_value, value, expecting_eol } state = expecting_key_name; std::pair entry{}; for (char& c : string_) { switch (state) { case expecting_key_name: switch (c) { case ' ': case '\t': case '\n': break; case '#': state = expecting_eol; break; default: entry.first = &c; state = key_name; break; } break; case key_name: 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_name; 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_name; 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_name; 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_name; 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_name; break; default: break; } break; } } if (entry.first && entry.second) entries_.push_back(entry); } const char* get_value(const char* section, const char* key_name, 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_name) + 1); entry_key.append(prefix_); if (!entry_key.empty()) entry_key.append("."); entry_key.append(section); entry_key.append("."); entry_key.append(key_name); for (const std::pair& entry : entries_) if (entry_key == entry.first) return entry.second; return nullptr; } private: std::string string_; std::string prefix_; std::vector> entries_; }; } // namespace detail void config_from_string::make(execution_context& ctx) const { (void)make_service(ctx, string_, prefix_); } namespace detail { #if defined(ASIO_MSVC) # pragma warning (push) # pragma warning (disable:4996) // suppress unsafe warning for std::getenv #endif // defined(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(prefix)) { } const char* get_value(const char* section, const char* key_name, 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_name) + 1); env_var.append(prefix_); if (!env_var.empty()) env_var.append("_"); env_var.append(section); env_var.append("_"); env_var.append(key_name); for (char& c : env_var) c = static_cast(std::toupper(static_cast(c))); return std::getenv(env_var.c_str()); } private: std::string prefix_; }; #if defined(ASIO_MSVC) # pragma warning (pop) #endif // defined(ASIO_MSVC) } // namespace detail config_from_env::config_from_env() : prefix_("asio") { } void config_from_env::make(execution_context& ctx) const { (void)make_service(ctx, prefix_); } } // namespace asio #include "asio/detail/pop_options.hpp" #endif // ASIO_IMPL_CONFIG_IPP