]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright Andrey Semashev 2007 - 2015. | |
3 | * Distributed under the Boost Software License, Version 1.0. | |
4 | * (See accompanying file LICENSE_1_0.txt or copy at | |
5 | * http://www.boost.org/LICENSE_1_0.txt) | |
6 | */ | |
7 | /*! | |
8 | * \file settings.hpp | |
9 | * \author Andrey Semashev | |
10 | * \date 11.10.2009 | |
11 | * | |
12 | * The header contains definition of the library settings container. | |
13 | */ | |
14 | ||
15 | #ifndef BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ | |
16 | #define BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ | |
17 | ||
18 | #include <cstddef> | |
19 | #include <string> | |
20 | #include <iterator> | |
21 | #include <boost/assert.hpp> | |
22 | #include <boost/move/core.hpp> | |
f67539c2 | 23 | #include <boost/type_traits/conditional.hpp> |
7c673cae FG |
24 | #include <boost/iterator/iterator_adaptor.hpp> |
25 | #include <boost/optional/optional.hpp> | |
26 | #include <boost/property_tree/ptree.hpp> | |
b32b8144 | 27 | #include <boost/core/explicit_operator_bool.hpp> |
7c673cae FG |
28 | #include <boost/log/detail/setup_config.hpp> |
29 | #include <boost/log/detail/native_typeof.hpp> | |
7c673cae FG |
30 | #if !defined(BOOST_LOG_TYPEOF) |
31 | #include <boost/core/enable_if.hpp> | |
32 | #endif | |
33 | #if defined(BOOST_LOG_TYPEOF) && defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) | |
34 | #include <boost/utility/declval.hpp> | |
35 | #endif | |
36 | #include <boost/log/detail/header.hpp> | |
37 | ||
38 | #ifdef BOOST_HAS_PRAGMA_ONCE | |
39 | #pragma once | |
40 | #endif | |
41 | ||
42 | namespace boost { | |
43 | ||
44 | BOOST_LOG_OPEN_NAMESPACE | |
45 | ||
46 | namespace aux { | |
47 | ||
48 | // This workaround is needed for MSVC 10 to work around ICE caused by stack overflow | |
49 | template< typename SectionT, bool IsConstV > | |
50 | struct basic_settings_section_iterator_base; | |
51 | ||
52 | template< typename SectionT > | |
53 | struct basic_settings_section_iterator_base< SectionT, true > | |
54 | { | |
55 | typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< true > iterator_type; | |
56 | typedef typename SectionT::property_tree_type::const_iterator base_iterator_type; | |
57 | typedef iterator_adaptor< | |
58 | iterator_type, | |
59 | base_iterator_type, | |
60 | SectionT, | |
61 | use_default, | |
62 | const SectionT | |
63 | > type; | |
64 | }; | |
65 | ||
66 | template< typename SectionT > | |
67 | struct basic_settings_section_iterator_base< SectionT, false > | |
68 | { | |
69 | typedef typename SectionT::BOOST_NESTED_TEMPLATE iter< false > iterator_type; | |
70 | typedef typename SectionT::property_tree_type::iterator base_iterator_type; | |
71 | typedef iterator_adaptor< | |
72 | iterator_type, | |
73 | base_iterator_type, | |
74 | SectionT, | |
75 | use_default, | |
76 | SectionT | |
77 | > type; | |
78 | }; | |
79 | ||
80 | } // namespace aux | |
81 | ||
82 | /*! | |
83 | * \brief The class represents a reference to the settings container section | |
84 | * | |
85 | * The section refers to a sub-tree of the library settings container. It does not | |
86 | * own the referred sub-tree but allows for convenient access to parameters within the subsection. | |
87 | */ | |
88 | template< typename CharT > | |
89 | class basic_settings_section | |
90 | { | |
91 | template< typename SectionT, bool IsConstV > | |
92 | friend struct aux::basic_settings_section_iterator_base; | |
93 | ||
94 | public: | |
95 | //! Character type | |
96 | typedef CharT char_type; | |
97 | //! String type | |
98 | typedef std::basic_string< char_type > string_type; | |
99 | //! Property tree type | |
100 | typedef property_tree::basic_ptree< std::string, string_type > property_tree_type; | |
101 | //! Property tree path type | |
102 | typedef typename property_tree_type::path_type path_type; | |
103 | ||
104 | private: | |
105 | #if !defined(BOOST_LOG_DOXYGEN_PASS) | |
106 | ||
107 | //! A reference proxy object | |
108 | #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS | |
109 | template< bool IsConstV > | |
110 | class ref; | |
111 | template< bool IsConstV > | |
112 | friend class ref; | |
113 | #endif | |
114 | template< bool IsConstV > | |
115 | class ref | |
116 | { | |
117 | private: | |
f67539c2 | 118 | typedef typename boost::conditional< |
7c673cae FG |
119 | IsConstV, |
120 | basic_settings_section< char_type > const, | |
121 | basic_settings_section< char_type > | |
122 | >::type section_type; | |
123 | ||
124 | private: | |
125 | section_type& m_section; | |
126 | path_type m_path; | |
127 | ||
128 | public: | |
129 | ref(section_type& section, std::string const& section_name) : | |
130 | m_section(section), | |
131 | m_path(section_name) | |
132 | { | |
133 | } | |
134 | ref(section_type& section, const char* section_name) : | |
135 | m_section(section), | |
136 | m_path(section_name) | |
137 | { | |
138 | } | |
139 | ||
140 | ref& operator[] (std::string const& param_name) | |
141 | { | |
142 | m_path /= param_name; | |
143 | return *this; | |
144 | } | |
145 | ||
146 | ref& operator= (string_type const& value) | |
147 | { | |
148 | BOOST_ASSERT(m_section.m_ptree != NULL); | |
149 | m_section.m_ptree->put(m_path, value); | |
150 | return *this; | |
151 | } | |
152 | ||
153 | template< bool V > | |
154 | ref& operator= (ref< V > const& value) | |
155 | { | |
156 | BOOST_ASSERT(m_section.m_ptree != NULL); | |
157 | optional< string_type > val = value.get(); | |
158 | if (!!val) | |
159 | { | |
160 | m_section.m_ptree->put(m_path, val); | |
161 | } | |
162 | else if (optional< property_tree_type& > node = m_section.m_ptree->get_child_optional(m_path)) | |
163 | { | |
164 | node.put_value(string_type()); | |
165 | } | |
166 | ||
167 | return *this; | |
168 | } | |
169 | ||
170 | template< typename T > | |
171 | ref& operator= (T const& value) | |
172 | { | |
173 | BOOST_ASSERT(m_section.m_ptree != NULL); | |
174 | m_section.m_ptree->put(m_path, value); | |
175 | return *this; | |
176 | } | |
177 | ||
178 | BOOST_EXPLICIT_OPERATOR_BOOL() | |
179 | ||
180 | bool operator! () const | |
181 | { | |
182 | return !m_section.m_ptree || !m_section.m_ptree->get_child_optional(m_path); | |
183 | } | |
184 | ||
185 | std::string get_name() const | |
186 | { | |
187 | return m_path.dump(); | |
188 | } | |
189 | ||
190 | operator optional< string_type > () const | |
191 | { | |
192 | return get(); | |
193 | } | |
194 | ||
195 | optional< string_type > get() const | |
196 | { | |
197 | if (m_section.m_ptree) | |
198 | return m_section.m_ptree->template get_optional< string_type >(m_path); | |
199 | else | |
200 | return optional< string_type >(); | |
201 | } | |
202 | ||
203 | template< typename T > | |
204 | optional< T > get() const | |
205 | { | |
206 | if (m_section.m_ptree) | |
207 | return m_section.m_ptree->template get_optional< T >(m_path); | |
208 | else | |
209 | return optional< T >(); | |
210 | } | |
211 | ||
212 | operator section_type () const | |
213 | { | |
214 | return get_section(); | |
215 | } | |
216 | ||
217 | section_type get_section() const | |
218 | { | |
219 | if (m_section.m_ptree) | |
220 | return section_type(m_section.m_ptree->get_child_optional(m_path).get_ptr()); | |
221 | else | |
222 | return section_type(); | |
223 | } | |
224 | ||
225 | #if defined(BOOST_LOG_TYPEOF) && !(defined(__GNUC__) && !defined(__INTEL_COMPILER) && !defined(__clang__) && !defined(__PATHSCALE__) && !defined(__GXX_EXPERIMENTAL_CXX0X__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 5)) | |
226 | #if !defined(BOOST_NO_CXX11_TRAILING_RESULT_TYPES) | |
227 | template< typename T > | |
228 | auto or_default(T const& def_value) const -> BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), def_value)) | |
229 | { | |
230 | if (m_section.m_ptree) | |
231 | return m_section.m_ptree->get(m_path, def_value); | |
232 | else | |
233 | return def_value; | |
234 | } | |
235 | #else | |
236 | // GCC up to 4.5 (inclusively) segfaults on the following code, if C++11 mode is not enabled | |
237 | template< typename T > | |
238 | BOOST_LOG_TYPEOF(property_tree_type().get(typename property_tree_type::path_type(), boost::declval< T >())) or_default(T const& def_value) const | |
239 | { | |
240 | if (m_section.m_ptree) | |
241 | return m_section.m_ptree->get(m_path, def_value); | |
242 | else | |
243 | return def_value; | |
244 | } | |
245 | #endif | |
246 | #else | |
247 | template< typename T > | |
248 | T or_default(T const& def_value) const | |
249 | { | |
250 | if (m_section.m_ptree) | |
251 | return m_section.m_ptree->get(m_path, def_value); | |
252 | else | |
253 | return def_value; | |
254 | } | |
255 | ||
256 | template< typename T > | |
257 | typename boost::enable_if_c< boost::property_tree::detail::is_character< T >::value, std::basic_string< T > >::type | |
258 | or_default(const T* def_value) const | |
259 | { | |
260 | if (m_section.m_ptree) | |
261 | return m_section.m_ptree->get(m_path, def_value); | |
262 | else | |
263 | return def_value; | |
264 | } | |
265 | #endif | |
266 | string_type or_default(string_type const& def_value) const | |
267 | { | |
268 | return get().get_value_or(def_value); | |
269 | } | |
270 | string_type or_default(typename string_type::value_type const* def_value) const | |
271 | { | |
272 | if (optional< string_type > val = get()) | |
273 | return val.get(); | |
274 | else | |
275 | return def_value; | |
276 | } | |
277 | }; | |
278 | ||
279 | //! An iterator over subsections and parameters | |
280 | #ifndef BOOST_LOG_NO_MEMBER_TEMPLATE_FRIENDS | |
281 | template< bool IsConstV > | |
282 | class iter; | |
283 | template< bool IsConstV > | |
284 | friend class iter; | |
285 | #endif | |
286 | template< bool IsConstV > | |
287 | class iter : | |
288 | public aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::type | |
289 | { | |
290 | friend class boost::iterator_core_access; | |
291 | ||
292 | typedef typename iter::iterator_adaptor_ iterator_adaptor_; | |
293 | // NOTE: This typedef must not come from iterator_adaptor_::base_type in order to work around MSVC 10 ICE | |
294 | typedef typename aux::basic_settings_section_iterator_base< basic_settings_section< char_type >, IsConstV >::base_iterator_type base_iterator_type; | |
295 | ||
296 | public: | |
297 | typedef typename iterator_adaptor_::reference reference; | |
298 | ||
299 | public: | |
300 | BOOST_DEFAULTED_FUNCTION(iter(), {}) | |
301 | template< bool OtherIsConstV > | |
302 | iter(iter< OtherIsConstV > const& that) : iterator_adaptor_(that.base()) {} | |
303 | explicit iter(base_iterator_type const& it) : iterator_adaptor_(it) {} | |
304 | ||
305 | //! Returns the section name | |
306 | std::string const& get_name() const | |
307 | { | |
308 | return this->base()->first; | |
309 | } | |
310 | ||
311 | private: | |
312 | reference dereference() const | |
313 | { | |
314 | return reference(const_cast< property_tree_type* >(&this->base()->second)); | |
315 | } | |
316 | }; | |
317 | ||
318 | public: | |
319 | typedef ref< true > const_reference; | |
320 | typedef ref< false > reference; | |
321 | typedef iter< true > const_iterator; | |
322 | typedef iter< false > iterator; | |
323 | typedef std::reverse_iterator< const_iterator > const_reverse_iterator; | |
324 | typedef std::reverse_iterator< iterator > reverse_iterator; | |
325 | ||
326 | #else | |
327 | ||
328 | public: | |
329 | /*! | |
330 | * Constant reference to the parameter value | |
331 | */ | |
332 | typedef implementation_defined const_reference; | |
333 | /*! | |
334 | * Mutable reference to the parameter value | |
335 | */ | |
336 | typedef implementation_defined reference; | |
337 | ||
338 | /*! | |
339 | * Constant iterator over nested parameters and subsections | |
340 | */ | |
341 | typedef implementation_defined const_iterator; | |
342 | /*! | |
343 | * Mutable iterator over nested parameters and subsections | |
344 | */ | |
345 | typedef implementation_defined iterator; | |
346 | ||
347 | #endif // !defined(BOOST_LOG_DOXYGEN_PASS) | |
348 | ||
349 | protected: | |
350 | //! Parameters | |
351 | property_tree_type* m_ptree; | |
352 | ||
353 | public: | |
354 | /*! | |
355 | * Default constructor. Creates an empty settings container. | |
356 | */ | |
20effc67 | 357 | basic_settings_section() BOOST_NOEXCEPT : m_ptree(NULL) |
7c673cae FG |
358 | { |
359 | } | |
360 | ||
361 | /*! | |
362 | * Copy constructor. | |
363 | */ | |
20effc67 | 364 | basic_settings_section(basic_settings_section const& that) BOOST_NOEXCEPT : m_ptree(that.m_ptree) |
7c673cae FG |
365 | { |
366 | } | |
367 | ||
368 | /*! | |
369 | * Checks if the section refers to the container. | |
370 | */ | |
371 | BOOST_EXPLICIT_OPERATOR_BOOL_NOEXCEPT() | |
372 | ||
373 | /*! | |
374 | * Checks if the section refers to the container. | |
375 | */ | |
376 | bool operator! () const BOOST_NOEXCEPT { return !m_ptree; } | |
377 | ||
378 | /*! | |
379 | * Returns an iterator over the nested subsections and parameters. | |
380 | */ | |
381 | iterator begin() | |
382 | { | |
383 | if (m_ptree) | |
384 | return iterator(m_ptree->begin()); | |
385 | else | |
386 | return iterator(); | |
387 | } | |
388 | ||
389 | /*! | |
390 | * Returns an iterator over the nested subsections and parameters. | |
391 | */ | |
392 | iterator end() | |
393 | { | |
394 | if (m_ptree) | |
395 | return iterator(m_ptree->end()); | |
396 | else | |
397 | return iterator(); | |
398 | } | |
399 | ||
400 | /*! | |
401 | * Returns an iterator over the nested subsections and parameters. | |
402 | */ | |
403 | const_iterator begin() const | |
404 | { | |
405 | if (m_ptree) | |
406 | return const_iterator(m_ptree->begin()); | |
407 | else | |
408 | return const_iterator(); | |
409 | } | |
410 | ||
411 | /*! | |
412 | * Returns an iterator over the nested subsections and parameters. | |
413 | */ | |
414 | const_iterator end() const | |
415 | { | |
416 | if (m_ptree) | |
417 | return const_iterator(m_ptree->end()); | |
418 | else | |
419 | return const_iterator(); | |
420 | } | |
421 | ||
422 | /*! | |
423 | * Returns a reverse iterator over the nested subsections and parameters. | |
424 | */ | |
425 | reverse_iterator rbegin() { return reverse_iterator(begin()); } | |
426 | ||
427 | /*! | |
428 | * Returns a reverse iterator over the nested subsections and parameters. | |
429 | */ | |
430 | reverse_iterator rend() { return reverse_iterator(end()); } | |
431 | ||
432 | /*! | |
433 | * Returns a reverse iterator over the nested subsections and parameters. | |
434 | */ | |
435 | const_reverse_iterator rbegin() const { return const_reverse_iterator(begin()); } | |
436 | ||
437 | /*! | |
438 | * Returns a reverse iterator over the nested subsections and parameters. | |
439 | */ | |
440 | const_reverse_iterator rend() const { return const_reverse_iterator(end()); } | |
441 | ||
442 | /*! | |
443 | * Checks if the container is empty (i.e. contains no sections and parameters). | |
444 | */ | |
445 | bool empty() const { return m_ptree == NULL || m_ptree->empty(); } | |
446 | ||
447 | /*! | |
448 | * Accessor to a single parameter. This operator should be used in conjunction | |
449 | * with the subsequent subscript operator that designates the parameter name. | |
450 | * | |
451 | * \param section_name The name of the section in which the parameter resides | |
452 | * \return An unspecified reference type that can be used for parameter name specifying | |
453 | */ | |
454 | reference operator[] (std::string const& section_name) { return reference(*this, section_name); } | |
455 | /*! | |
456 | * Accessor to a single parameter. This operator should be used in conjunction | |
457 | * with the subsequent subscript operator that designates the parameter name. | |
458 | * | |
459 | * \param section_name The name of the section in which the parameter resides | |
460 | * \return An unspecified reference type that can be used for parameter name specifying | |
461 | */ | |
462 | const_reference operator[] (std::string const& section_name) const { return const_reference(*this, section_name); } | |
463 | ||
464 | /*! | |
465 | * Accessor to a single parameter. This operator should be used in conjunction | |
466 | * with the subsequent subscript operator that designates the parameter name. | |
467 | * | |
468 | * \param section_name The name of the section in which the parameter resides | |
469 | * \return An unspecified reference type that can be used for parameter name specifying | |
470 | */ | |
471 | reference operator[] (const char* section_name) { return reference(*this, section_name); } | |
472 | /*! | |
473 | * Accessor to a single parameter. This operator should be used in conjunction | |
474 | * with the subsequent subscript operator that designates the parameter name. | |
475 | * | |
476 | * \param section_name The name of the section in which the parameter resides | |
477 | * \return An unspecified reference type that can be used for parameter name specifying | |
478 | */ | |
479 | const_reference operator[] (const char* section_name) const { return const_reference(*this, section_name); } | |
480 | ||
481 | /*! | |
482 | * Accessor for the embedded property tree | |
483 | */ | |
484 | property_tree_type const& property_tree() const { return *m_ptree; } | |
485 | /*! | |
486 | * Accessor for the embedded property tree | |
487 | */ | |
488 | property_tree_type& property_tree() { return *m_ptree; } | |
489 | ||
490 | /*! | |
491 | * Checks if the specified section is present in the container. | |
492 | * | |
493 | * \param section_name The name of the section | |
494 | */ | |
495 | bool has_section(string_type const& section_name) const | |
496 | { | |
497 | return m_ptree != NULL && !!m_ptree->get_child_optional(section_name); | |
498 | } | |
499 | /*! | |
500 | * Checks if the specified parameter is present in the container. | |
501 | * | |
502 | * \param section_name The name of the section in which the parameter resides | |
503 | * \param param_name The name of the parameter | |
504 | */ | |
505 | bool has_parameter(string_type const& section_name, string_type const& param_name) const | |
506 | { | |
507 | if (m_ptree) | |
508 | { | |
509 | optional< property_tree_type& > section = m_ptree->get_child_optional(section_name); | |
510 | if (!!section) | |
511 | return (section->find(param_name) != section->not_found()); | |
512 | } | |
513 | ||
514 | return false; | |
515 | } | |
516 | ||
517 | /*! | |
518 | * Swaps two references to settings sections. | |
519 | */ | |
20effc67 | 520 | void swap(basic_settings_section& that) BOOST_NOEXCEPT |
7c673cae FG |
521 | { |
522 | property_tree_type* const p = m_ptree; | |
523 | m_ptree = that.m_ptree; | |
524 | that.m_ptree = p; | |
525 | } | |
526 | ||
527 | protected: | |
20effc67 | 528 | explicit basic_settings_section(property_tree_type* tree) BOOST_NOEXCEPT : m_ptree(tree) |
7c673cae FG |
529 | { |
530 | } | |
531 | }; | |
532 | ||
533 | template< typename CharT > | |
20effc67 | 534 | inline void swap(basic_settings_section< CharT >& left, basic_settings_section< CharT >& right) BOOST_NOEXCEPT |
7c673cae FG |
535 | { |
536 | left.swap(right); | |
537 | } | |
538 | ||
539 | ||
540 | /*! | |
541 | * \brief The class represents settings container | |
542 | * | |
543 | * All settings are presented as a number of named parameters divided into named sections. | |
544 | * The parameters values are stored as strings. Individual parameters may be queried via subscript operators, like this: | |
545 | * | |
546 | * <code><pre> | |
547 | * optional< string > param = settings["Section1"]["Param1"]; // reads parameter "Param1" in section "Section1" | |
548 | * // returns an empty value if no such parameter exists | |
549 | * settings["Section2"]["Param2"] = 10; // sets the parameter "Param2" in section "Section2" | |
550 | * // to value "10" | |
551 | * </pre></code> | |
552 | * | |
553 | * There are also other methods to work with parameters. | |
554 | */ | |
555 | template< typename CharT > | |
556 | class basic_settings : | |
557 | public basic_settings_section< CharT > | |
558 | { | |
559 | typedef basic_settings this_type; | |
560 | BOOST_COPYABLE_AND_MOVABLE(this_type) | |
561 | ||
562 | public: | |
563 | //! Section type | |
564 | typedef basic_settings_section< CharT > section; | |
565 | //! Property tree type | |
566 | typedef typename section::property_tree_type property_tree_type; | |
567 | ||
568 | public: | |
569 | /*! | |
570 | * Default constructor. Creates an empty settings container. | |
571 | */ | |
572 | basic_settings() : section(new property_tree_type()) | |
573 | { | |
574 | } | |
575 | ||
576 | /*! | |
577 | * Copy constructor. | |
578 | */ | |
579 | basic_settings(basic_settings const& that) : | |
580 | section(that.m_ptree ? new property_tree_type(*that.m_ptree) : static_cast< property_tree_type* >(NULL)) | |
581 | { | |
582 | } | |
583 | ||
584 | /*! | |
585 | * Move constructor. | |
586 | */ | |
20effc67 | 587 | basic_settings(BOOST_RV_REF(this_type) that) BOOST_NOEXCEPT |
7c673cae FG |
588 | { |
589 | this->swap(that); | |
590 | } | |
591 | /*! | |
592 | * Initializing constructor. Creates a settings container with the copy of the specified property tree. | |
593 | */ | |
594 | explicit basic_settings(property_tree_type const& tree) : section(new property_tree_type(tree)) | |
595 | { | |
596 | } | |
597 | ||
598 | /*! | |
599 | * Destructor | |
600 | */ | |
20effc67 | 601 | ~basic_settings() BOOST_NOEXCEPT |
7c673cae FG |
602 | { |
603 | delete this->m_ptree; | |
604 | } | |
605 | ||
606 | /*! | |
607 | * Copy assignment operator. | |
608 | */ | |
609 | basic_settings& operator= (BOOST_COPY_ASSIGN_REF(basic_settings) that) | |
610 | { | |
611 | if (this != &that) | |
612 | { | |
613 | basic_settings tmp = that; | |
614 | this->swap(tmp); | |
615 | } | |
616 | return *this; | |
617 | } | |
618 | /*! | |
619 | * Move assignment operator. | |
620 | */ | |
20effc67 | 621 | basic_settings& operator= (BOOST_RV_REF(basic_settings) that) BOOST_NOEXCEPT |
7c673cae FG |
622 | { |
623 | this->swap(that); | |
624 | return *this; | |
625 | } | |
626 | }; | |
627 | ||
628 | #ifdef BOOST_LOG_USE_CHAR | |
629 | typedef basic_settings< char > settings; //!< Convenience typedef for narrow-character logging | |
630 | typedef basic_settings_section< char > settings_section; //!< Convenience typedef for narrow-character logging | |
631 | #endif | |
632 | #ifdef BOOST_LOG_USE_WCHAR_T | |
633 | typedef basic_settings< wchar_t > wsettings; //!< Convenience typedef for wide-character logging | |
634 | typedef basic_settings_section< wchar_t > wsettings_section; //!< Convenience typedef for wide-character logging | |
635 | #endif | |
636 | ||
637 | BOOST_LOG_CLOSE_NAMESPACE // namespace log | |
638 | ||
639 | } // namespace boost | |
640 | ||
641 | #include <boost/log/detail/footer.hpp> | |
642 | ||
643 | #endif // BOOST_LOG_UTILITY_SETUP_SETTINGS_HPP_INCLUDED_ |