File indexing completed on 2025-09-16 08:29:00
0001
0002
0003
0004
0005
0006
0007
0008
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
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* ,
0042 const char* , char* , std::size_t ) 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 }
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* , std::size_t ) 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 }
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)
0283 #endif
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* , std::size_t ) 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
0320
0321 }
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 }
0334 }
0335
0336 #include <boost/asio/detail/pop_options.hpp>
0337
0338 #endif