Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-16 08:29:00

0001 //
0002 // impl/config.ipp
0003 // ~~~~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2025 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_IMPL_CONFIG_IPP
0012 #define BOOST_ASIO_IMPL_CONFIG_IPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/config.hpp>
0019 #include <boost/asio/detail/concurrency_hint.hpp>
0020 #include <cctype>
0021 #include <cstdio>
0022 #include <cstring>
0023 #include <cstdlib>
0024 #include <vector>
0025 #include <utility>
0026 
0027 #include <boost/asio/detail/push_options.hpp>
0028 
0029 namespace boost {
0030 namespace asio {
0031 
0032 config_service::config_service(execution_context& ctx)
0033   : detail::execution_context_service_base<config_service>(ctx)
0034 {
0035 }
0036 
0037 void config_service::shutdown()
0038 {
0039 }
0040 
0041 const char* config_service::get_value(const char* /*section*/,
0042     const char* /*key*/, char* /*value*/, std::size_t /*value_len*/) const
0043 {
0044   return nullptr;
0045 }
0046 
0047 namespace detail {
0048 
0049 class config_from_concurrency_hint_service : public config_service
0050 {
0051 public:
0052   explicit config_from_concurrency_hint_service(
0053       execution_context& ctx, int concurrency_hint)
0054     : config_service(ctx),
0055       concurrency_hint_(concurrency_hint)
0056   {
0057   }
0058 
0059   const char* get_value(const char* section, const char* key,
0060       char* value, std::size_t value_len) const override
0061   {
0062     if (std::strcmp(section, "scheduler") == 0)
0063     {
0064       if (std::strcmp(key, "concurrency_hint") == 0)
0065       {
0066         std::snprintf(value, value_len, "%d",
0067             BOOST_ASIO_CONCURRENCY_HINT_IS_SPECIAL(concurrency_hint_)
0068               ? 1 : concurrency_hint_);
0069         return value;
0070       }
0071       else if (std::strcmp(key, "locking") == 0)
0072       {
0073         return BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
0074             SCHEDULER, concurrency_hint_) ? "1" : "0";
0075       }
0076     }
0077     else if (std::strcmp(section, "reactor") == 0)
0078     {
0079       if (std::strcmp(key, "io_locking") == 0)
0080       {
0081         return BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
0082             REACTOR_IO, concurrency_hint_) ? "1" : "0";
0083       }
0084       else if (std::strcmp(key, "registration_locking") == 0)
0085       {
0086         return BOOST_ASIO_CONCURRENCY_HINT_IS_LOCKING(
0087             REACTOR_REGISTRATION, concurrency_hint_) ? "1" : "0";
0088       }
0089     }
0090     return nullptr;
0091   }
0092 
0093 private:
0094   int concurrency_hint_;
0095 };
0096 
0097 } // namespace detail
0098 
0099 config_from_concurrency_hint::config_from_concurrency_hint()
0100   : concurrency_hint_(BOOST_ASIO_CONCURRENCY_HINT_DEFAULT)
0101 {
0102 }
0103 
0104 void config_from_concurrency_hint::make(execution_context& ctx) const
0105 {
0106   (void)make_service<detail::config_from_concurrency_hint_service>(ctx,
0107       concurrency_hint_ == 1
0108         ? BOOST_ASIO_CONCURRENCY_HINT_1 : concurrency_hint_);
0109 }
0110 
0111 namespace detail {
0112 
0113 class config_from_string_service : public config_service
0114 {
0115 public:
0116   config_from_string_service(execution_context& ctx,
0117       std::string s, std::string prefix)
0118     : config_service(ctx),
0119       string_(static_cast<std::string&&>(s)),
0120       prefix_(static_cast<std::string&&>(prefix))
0121   {
0122     enum
0123     {
0124       expecting_key,
0125       key,
0126       expecting_equals,
0127       expecting_value,
0128       value,
0129       expecting_eol
0130     } state = expecting_key;
0131     std::pair<const char*, const char*> entry{};
0132 
0133     for (char& c : string_)
0134     {
0135       switch (state)
0136       {
0137       case expecting_key:
0138         switch (c)
0139         {
0140         case ' ': case '\t': case '\n':
0141           break;
0142         case '#':
0143           state = expecting_eol;
0144           break;
0145         default:
0146           entry.first = &c;
0147           state = key;
0148           break;
0149         }
0150         break;
0151       case key:
0152         switch (c)
0153         {
0154         case ' ': case '\t':
0155           c = 0;
0156           state = expecting_equals;
0157           break;
0158         case '=':
0159           c = 0;
0160           state = expecting_value;
0161           break;
0162         case '\n':
0163           entry.first = nullptr;
0164           state = expecting_key;
0165           break;
0166         case '#':
0167           entry.first = nullptr;
0168           state = expecting_eol;
0169           break;
0170         default:
0171           break;
0172         }
0173         break;
0174       case expecting_equals:
0175         switch (c)
0176         {
0177         case ' ': case '\t':
0178           break;
0179         case '=':
0180           state = expecting_value;
0181           break;
0182         case '\n':
0183           entry.first = nullptr;
0184           state = expecting_key;
0185           break;
0186         default:
0187           entry.first = nullptr;
0188           state = expecting_eol;
0189           break;
0190         }
0191         break;
0192       case expecting_value:
0193         switch (c)
0194         {
0195         case ' ': case '\t':
0196           break;
0197         case '\n':
0198           entry.first = nullptr;
0199           state = expecting_key;
0200           break;
0201         case '#':
0202           entry.first = nullptr;
0203           state = expecting_eol;
0204           break;
0205         default:
0206           entry.second = &c;
0207           state = value;
0208           break;
0209         }
0210         break;
0211       case value:
0212         switch (c)
0213         {
0214         case '\n':
0215           c = 0;
0216           entries_.push_back(entry);
0217           entry.first = entry.second = nullptr;
0218           state = expecting_key;
0219           break;
0220         case '#':
0221           c = 0;
0222           entries_.push_back(entry);
0223           entry.first = entry.second = nullptr;
0224           state = expecting_eol;
0225           break;
0226         default:
0227           break;
0228         }
0229         break;
0230       case expecting_eol:
0231         switch (c)
0232         {
0233         case '\n':
0234           state = expecting_key;
0235           break;
0236         default:
0237           break;
0238         }
0239         break;
0240       }
0241     }
0242     if (entry.first && entry.second)
0243       entries_.push_back(entry);
0244   }
0245 
0246   const char* get_value(const char* section, const char* key,
0247       char* /*value*/, std::size_t /*value_len*/) const override
0248   {
0249     std::string entry_key;
0250     entry_key.reserve(prefix_.length() + 1
0251         + std::strlen(section) + 1
0252         + std::strlen(key) + 1);
0253     entry_key.append(prefix_);
0254     if (!entry_key.empty())
0255       entry_key.append(".");
0256     entry_key.append(section);
0257     entry_key.append(".");
0258     entry_key.append(key);
0259     for (const std::pair<const char*, const char*>& entry : entries_)
0260       if (entry_key == entry.first)
0261         return entry.second;
0262     return nullptr;
0263   }
0264 
0265 private:
0266   std::string string_;
0267   std::string prefix_;
0268   std::vector<std::pair<const char*, const char*>> entries_;
0269 };
0270 
0271 } // namespace detail
0272 
0273 void config_from_string::make(execution_context& ctx) const
0274 {
0275   (void)make_service<detail::config_from_string_service>(ctx, string_, prefix_);
0276 }
0277 
0278 namespace detail {
0279 
0280 #if defined(BOOST_ASIO_MSVC)
0281 # pragma warning (push)
0282 # pragma warning (disable:4996) // suppress unsafe warning for std::getenv
0283 #endif // defined(BOOST_ASIO_MSVC)
0284 
0285 class config_from_env_service : public config_service
0286 {
0287 public:
0288   explicit config_from_env_service(
0289       execution_context& ctx, std::string prefix)
0290     : config_service(ctx),
0291       prefix_(static_cast<std::string&&>(prefix))
0292   {
0293   }
0294 
0295   const char* get_value(const char* section, const char* key,
0296       char* /*value*/, std::size_t /*value_len*/) const override
0297   {
0298     std::string env_var;
0299     env_var.reserve(prefix_.length() + 1
0300         + std::strlen(section) + 1
0301         + std::strlen(key) + 1);
0302     env_var.append(prefix_);
0303     if (!env_var.empty())
0304       env_var.append("_");
0305     env_var.append(section);
0306     env_var.append("_");
0307     env_var.append(key);
0308     for (char& c : env_var)
0309       c = static_cast<char>(std::toupper(static_cast<unsigned char>(c)));
0310     return std::getenv(env_var.c_str());
0311   }
0312 
0313 private:
0314   std::string prefix_;
0315 };
0316 
0317 #if defined(BOOST_ASIO_MSVC)
0318 # pragma warning (pop)
0319 #endif // defined(BOOST_ASIO_MSVC)
0320 
0321 } // namespace detail
0322 
0323 config_from_env::config_from_env()
0324   : prefix_("asio")
0325 {
0326 }
0327 
0328 void config_from_env::make(execution_context& ctx) const
0329 {
0330   (void)make_service<detail::config_from_env_service>(ctx, prefix_);
0331 }
0332 
0333 } // namespace asio
0334 } // namespace boost
0335 
0336 #include <boost/asio/detail/pop_options.hpp>
0337 
0338 #endif // BOOST_ASIO_IMPL_CONFIG_IPP