1 // Copyright (C) 2014-2021 Internet Systems Consortium, Inc. ("ISC") 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, v. 2.0. If a copy of the MPL was not distributed with this 5 // file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 7 #ifndef CFG_OPTION_H 8 #define CFG_OPTION_H 9 10 #include <dhcp/option.h> 11 #include <dhcp/option_space_container.h> 12 #include <cc/cfg_to_element.h> 13 #include <cc/stamped_element.h> 14 #include <cc/user_context.h> 15 #include <dhcpsrv/cfg_option_def.h> 16 #include <dhcpsrv/key_from_key.h> 17 #include <boost/multi_index_container.hpp> 18 #include <boost/multi_index/hashed_index.hpp> 19 #include <boost/multi_index/ordered_index.hpp> 20 #include <boost/multi_index/sequenced_index.hpp> 21 #include <boost/multi_index/mem_fun.hpp> 22 #include <boost/multi_index/member.hpp> 23 #include <boost/shared_ptr.hpp> 24 #include <stdint.h> 25 #include <string> 26 #include <list> 27 28 namespace isc { 29 namespace dhcp { 30 31 class OptionDescriptor; 32 33 /// A pointer to option descriptor. 34 typedef boost::shared_ptr<OptionDescriptor> OptionDescriptorPtr; 35 36 /// @brief Option descriptor. 37 /// 38 /// Option descriptor holds instance of an option and additional information 39 /// for this option. This information comprises whether this option is sent 40 /// to DHCP client only on request (persistent = false) or always 41 /// (persistent = true). 42 class OptionDescriptor : public data::StampedElement, public data::UserContext { 43 public: 44 /// @brief Option instance. 45 OptionPtr option_; 46 47 /// @brief Persistence flag. 48 /// 49 /// If true, option is always sent to the client. If false, option is 50 /// sent to the client when requested using ORO or PRL option. 51 bool persistent_; 52 53 /// @brief Option value in textual (CSV) format. 54 /// 55 /// This field is used to convey option value in human readable format, 56 /// the same as used to specify option value in the server configuration. 57 /// This value is optional and can be held in the host reservations 58 /// database instead of the binary format. 59 /// 60 /// Note that this value is carried in the option descriptor, rather than 61 /// @c Option instance because it is a server specific value (same as 62 /// persistence flag). 63 /// 64 /// An example of the formatted value is: "2001:db8:1::1, 23, some text" 65 /// for the option which carries IPv6 address, a number and a text. 66 std::string formatted_value_; 67 68 /// @brief Option space name. 69 /// 70 /// Options are associated with option spaces. Typically, such association 71 /// is made when the option is stored in the @c OptionContainer. However, 72 /// in some cases it is also required to associate option with the particular 73 /// option space outside of the container. In particular, when the option 74 /// is fetched from a database. The database configuration backend will 75 /// set option space upon return of the option. In other cases this value 76 /// won't be set. 77 std::string space_name_; 78 79 /// @brief Constructor. 80 /// 81 /// @param opt option instance. 82 /// @param persist if true, option is always sent. 83 /// @param formatted_value option value in the textual format (optional). 84 /// @param user_context user context (optional). 85 OptionDescriptor(const OptionPtr& opt, bool persist, 86 const std::string& formatted_value = "", 87 data::ConstElementPtr user_context = data::ConstElementPtr()) StampedElement()88 : data::StampedElement(), option_(opt), persistent_(persist), 89 formatted_value_(formatted_value), 90 space_name_() { 91 setContext(user_context); 92 }; 93 94 /// @brief Constructor. 95 /// 96 /// @param persist if true option is always sent. OptionDescriptor(bool persist)97 OptionDescriptor(bool persist) 98 : data::StampedElement(), option_(OptionPtr()), persistent_(persist), 99 formatted_value_(), space_name_() {}; 100 101 /// @brief Copy constructor. 102 /// 103 /// @param desc option descriptor to be copied. OptionDescriptor(const OptionDescriptor & desc)104 OptionDescriptor(const OptionDescriptor& desc) 105 : data::StampedElement(desc), 106 option_(desc.option_), 107 persistent_(desc.persistent_), 108 formatted_value_(desc.formatted_value_), 109 space_name_(desc.space_name_) { 110 setContext(desc.getContext()); 111 }; 112 113 /// @brief Assignment operator. 114 /// 115 /// @param other option descriptor to be assigned from. 116 OptionDescriptor& operator=(const OptionDescriptor& other) { 117 if (this != &other) { 118 // Not self-assignment. 119 data::StampedElement::operator=(other); 120 option_ = other.option_; 121 persistent_ = other.persistent_; 122 formatted_value_ = other.formatted_value_; 123 space_name_ = other.space_name_; 124 setContext(other.getContext()); 125 } 126 return (*this); 127 } 128 129 /// @brief Factory function creating an instance of the @c OptionDescriptor. 130 /// 131 /// @param opt option instance. 132 /// @param persist if true, option is always sent. 133 /// @param formatted_value option value in the textual format (optional). 134 /// @param user_context user context (optional). 135 /// 136 /// @return Pointer to the @c OptionDescriptor instance. 137 static OptionDescriptorPtr create(const OptionPtr& opt, 138 bool persist, 139 const std::string& formatted_value = "", 140 data::ConstElementPtr user_context = 141 data::ConstElementPtr()); 142 143 /// @brief Factory function creating an instance of the @c OptionDescriptor. 144 /// 145 /// @param persist if true option is always sent. 146 /// 147 /// @return Pointer to the @c OptionDescriptor instance. 148 static OptionDescriptorPtr create(bool persist); 149 150 /// @brief Factory function creating an instance of the @c OptionDescriptor. 151 /// 152 /// @param desc option descriptor to be copied. 153 /// 154 /// @return Pointer to the @c OptionDescriptor instance. 155 static OptionDescriptorPtr create(const OptionDescriptor& desc); 156 157 /// @brief Checks if the one descriptor is equal to another. 158 /// 159 /// @param other Other option descriptor to compare to. 160 /// 161 /// @return true if descriptors equal, false otherwise. 162 bool equals(const OptionDescriptor& other) const; 163 164 /// @brief Equality operator. 165 /// 166 /// @param other Other option descriptor to compare to. 167 /// 168 /// @return true if descriptors equal, false otherwise. 169 bool operator==(const OptionDescriptor& other) const { 170 return (equals(other)); 171 } 172 173 /// @brief Inequality operator. 174 /// 175 /// @param other Other option descriptor to compare to. 176 /// 177 /// @return true if descriptors unequal, false otherwise. 178 bool operator!=(const OptionDescriptor& other) const { 179 return (!equals(other)); 180 } 181 }; 182 183 /// @brief Multi index container for DHCP option descriptors. 184 /// 185 /// This container comprises three indexes to access option 186 /// descriptors: 187 /// - sequenced index: used to access elements in the order they 188 /// have been added to the container, 189 /// - option type index: used to search option descriptors containing 190 /// options with specific option code (aka option type). 191 /// - persistency flag index: used to search option descriptors with 192 /// 'persistent' flag set to true. 193 /// 194 /// This container is the equivalent of three separate STL containers: 195 /// - std::list of all options, 196 /// - std::multimap of options with option code used as a multimap key, 197 /// - std::multimap of option descriptors with option persistency flag 198 /// used as a multimap key. 199 /// The major advantage of this container over 3 separate STL containers 200 /// is automatic synchronization of all indexes when elements are added, 201 /// removed or modified in the container. With separate containers, 202 /// the synchronization would have to be guaranteed by the Subnet class 203 /// code. This would increase code complexity and presumably it would 204 /// be much harder to add new search criteria (indexes). 205 /// 206 /// @todo we may want to search for options using option spaces when 207 /// they are implemented. 208 /// 209 /// @see http://www.boost.org/doc/libs/1_51_0/libs/multi_index/doc/index.html 210 typedef boost::multi_index_container< 211 // Container comprises elements of OptionDescriptor type. 212 OptionDescriptor, 213 // Here we start enumerating various indexes. 214 boost::multi_index::indexed_by< 215 // Sequenced index allows accessing elements in the same way 216 // as elements in std::list. 217 // Sequenced is an index #0. 218 boost::multi_index::sequenced<>, 219 // Start definition of index #1. 220 boost::multi_index::hashed_non_unique< 221 // KeyFromKeyExtractor is the index key extractor that allows 222 // accessing option type being held by the OptionPtr through 223 // OptionDescriptor structure. 224 KeyFromKeyExtractor< 225 // Use option type as the index key. The type is held 226 // in OptionPtr object so we have to call Option::getType 227 // to retrieve this key for each element. 228 boost::multi_index::const_mem_fun< 229 Option, 230 uint16_t, 231 &Option::getType 232 >, 233 // Indicate that OptionPtr is a member of 234 // OptionDescriptor structure. 235 boost::multi_index::member< 236 OptionDescriptor, 237 OptionPtr, 238 &OptionDescriptor::option_ 239 > 240 > 241 >, 242 // Start definition of index #2. 243 // Use 'persistent' struct member as a key. 244 boost::multi_index::hashed_non_unique< 245 boost::multi_index::member< 246 OptionDescriptor, 247 bool, 248 &OptionDescriptor::persistent_ 249 > 250 >, 251 // Start definition of index #3. 252 // Use BaseStampedElement::getModificationTime as a key. 253 boost::multi_index::ordered_non_unique< 254 boost::multi_index::const_mem_fun< 255 data::BaseStampedElement, 256 boost::posix_time::ptime, 257 &data::BaseStampedElement::getModificationTime 258 > 259 >, 260 261 // Start definition of index #4. 262 // Use BaseStampedElement::getId as a key. 263 boost::multi_index::hashed_non_unique< 264 boost::multi_index::tag<OptionIdIndexTag>, 265 boost::multi_index::const_mem_fun<data::BaseStampedElement, uint64_t, 266 &data::BaseStampedElement::getId> 267 > 268 > 269 > OptionContainer; 270 271 /// Pointer to the OptionContainer object. 272 typedef boost::shared_ptr<OptionContainer> OptionContainerPtr; 273 /// Type of the index #1 - option type. 274 typedef OptionContainer::nth_index<1>::type OptionContainerTypeIndex; 275 /// Pair of iterators to represent the range of options having the 276 /// same option type value. The first element in this pair represents 277 /// the beginning of the range, the second element represents the end. 278 typedef std::pair<OptionContainerTypeIndex::const_iterator, 279 OptionContainerTypeIndex::const_iterator> OptionContainerTypeRange; 280 /// Type of the index #2 - option persistency flag. 281 typedef OptionContainer::nth_index<2>::type OptionContainerPersistIndex; 282 /// Pair of iterators to represent the range of options having the 283 /// same persistency flag. The first element in this pair represents 284 /// the beginning of the range, the second element represents the end. 285 typedef std::pair<OptionContainerPersistIndex::const_iterator, 286 OptionContainerPersistIndex::const_iterator> OptionContainerPersistRange; 287 288 /// @brief Represents option data configuration for the DHCP server. 289 /// 290 /// This class holds a collection of options to be sent to a DHCP client. 291 /// Options are grouped by the option space or vendor identifier (for 292 /// vendor options). 293 /// 294 /// The server configuration allows for specifying two distinct collections 295 /// of options: global options and per-subnet options in which some options 296 /// may overlap. 297 /// 298 /// The collection of global options specify options being sent to the client 299 /// belonging to any subnets, i.e. global options are "inherited" by all 300 /// subnets. 301 /// 302 /// The per-subnet options are configured for a particular subnet and are sent 303 /// to clients which belong to this subnet. The values of the options specified 304 /// for a particular subnet override the values of the global options. 305 /// 306 /// This class represents a single collection of options (either global or 307 /// per-subnet). Each subnet holds its own object of the @c CfgOption type. The 308 /// @c CfgMgr holds a @c CfgOption object representing global options. 309 /// 310 /// Note that having a separate copy of the @c CfgOption to represent global 311 /// options is useful when the client requests stateless configuration from 312 /// the DHCP server and no subnet is selected for this client. This client 313 /// will only receive global options. 314 class CfgOption : public isc::data::CfgToElement { 315 public: 316 317 /// @brief default constructor 318 CfgOption(); 319 320 /// @brief Indicates the object is empty 321 /// 322 /// @return true when the object is empty 323 bool empty() const; 324 325 /// @name Methods and operators used for comparing objects. 326 /// 327 //@{ 328 /// @brief Check if configuration is equal to other configuration. 329 /// 330 /// @param other An object holding configuration to compare to. 331 /// 332 /// @return true if configurations are equal, false otherwise. 333 bool equals(const CfgOption& other) const; 334 335 /// @brief Equality operator. 336 /// 337 /// @param other An object holding configuration to compare to. 338 /// 339 /// @return true if configurations are equal, false otherwise. 340 bool operator==(const CfgOption& other) const { 341 return (equals(other)); 342 } 343 344 /// @brief Inequality operator. 345 /// 346 /// @param other An object holding configuration to compare to. 347 /// 348 /// @return true if configurations are unequal, false otherwise. 349 bool operator!=(const CfgOption& other) const { 350 return (!equals(other)); 351 } 352 353 //@} 354 355 /// @brief Adds instance of the option to the configuration. 356 /// 357 /// There are two types of options which may be passed to this method: 358 /// - vendor options 359 /// - non-vendor options 360 /// 361 /// The non-vendor options are grouped by the name of the option space 362 /// (specified in textual format). The vendor options are grouped by the 363 /// vendor identifier, which is a 32-bit unsigned integer value. 364 /// 365 /// In order to add new vendor option to the list the option space name 366 /// (last argument of this method) should be specified as "vendor-X" where 367 /// "X" is a 32-bit unsigned integer, e.g. "vendor-1234". Options for which 368 /// the @c option_space argument doesn't follow this format are added as 369 /// non-vendor options. 370 /// 371 /// @param option Pointer to the option being added. 372 /// @param persistent Boolean value which specifies if the option should 373 /// be sent to the client regardless if requested (true), or nor (false) 374 /// @param option_space Option space name. 375 /// @param id Optional database id to be associated with the option. 376 /// 377 /// @throw isc::BadValue if the option space is invalid. 378 void add(const OptionPtr& option, const bool persistent, 379 const std::string& option_space, 380 const uint64_t id = 0); 381 382 /// @brief A variant of the @ref CfgOption::add method which takes option 383 /// descriptor as an argument. 384 /// 385 /// @param desc Option descriptor holding option instance and other 386 /// parameters pertaining to the option. 387 /// @param option_space Option space name. 388 /// 389 /// @throw isc::BadValue if the option space is invalid. 390 void add(const OptionDescriptor& desc, const std::string& option_space); 391 392 /// @brief Replaces the instance of an option within this collection 393 /// 394 /// This method locates the option within the given space and replaces 395 /// it with a copy of the given descriptor. This effectively updates 396 /// the contents without altering the container indexing. 397 /// 398 /// @param desc Option descriptor holding option instance and other 399 /// parameters pertaining to the option. 400 /// @param option_space Option space name. 401 /// 402 /// @throw isc::BadValue if the descriptor's option instance is null, 403 /// if space is invalid, or if the option does not already exist 404 /// in the given space. 405 void replace(const OptionDescriptor& desc, const std::string& option_space); 406 407 /// @brief Merges another option configuration into this one. 408 /// 409 /// This method calls @c mergeTo() to add this configuration's 410 /// options into @c other (skipping any duplicates). Next it calls 411 /// @c createDescriptorOption() for each option descriptor in the 412 /// merged set. This (re)-creates each descriptor's option based on 413 /// the merged set of opt definitions. Finally, it calls 414 /// @c copyTo() to overwrite this configuration's options with 415 /// the merged set in @c other. 416 /// 417 /// @warning The merge operation will affect the @c other configuration. 418 /// Therefore, the caller must not rely on the data held in the @c other 419 /// object after the call to @c merge. Also, the data held in @c other must 420 /// not be modified after the call to @c merge because it may affect the 421 /// merged configuration. 422 /// 423 /// @param cfg_def set of of user-defined option definitions to use 424 /// when merging. 425 /// @param other option configuration to merge in. 426 void merge(CfgOptionDefPtr cfg_def, CfgOption& other); 427 428 /// @brief Re-create the option in each descriptor based on given definitions 429 /// 430 /// Invokes @c createDescriptorOption() on each option descriptor in 431 /// each option space, passing in the given dictionary of option 432 /// definitions. If the descriptor's option is re-created, then the 433 /// descriptor is updated by calling @c replace(). 434 /// 435 /// @param cfg_def set of of user-defined option definitions to use 436 /// when creating option instances. 437 void createOptions(CfgOptionDefPtr cfg_def); 438 439 /// @brief Creates an option descriptor's option based on a set of option defs 440 /// 441 /// This function's primary use is to create definition specific options for 442 /// option descriptors fetched from a configuration backend, as part of a 443 /// configuration merge. 444 /// 445 /// Given an OptionDescriptor whose option_ member contains a generic option 446 /// (i.e has a code and/or data), this function will attempt to find a matching 447 /// definition and then use that definition's factory to create an option 448 /// instance specific to that definition. It will then replace the descriptor's 449 /// generic option with the specific option. 450 /// 451 /// Three sources of definitions are searched, in the following order: 452 /// 453 /// 1. Standard option definitions (@c LIBDHCP::getOptionDef)) 454 /// 2. Vendor option definitions (@c LIBDHCP::getVendorOptionDef)) 455 /// 3. User specified definitions passed in via cfg_def parameter. 456 /// 457 /// The code will use the first matching definition found. It then applies 458 /// the following rules: 459 /// 460 /// -# If no definition is found but the descriptor conveys a non-empty 461 /// formatted value, throw an error. 462 /// -# If not definition is found and there is no formatted value, return 463 /// This leaves intact the generic option in the descriptor. 464 /// -# If a definition is found and there is no formatted value, pass the 465 /// descriptor's generic option's data into the definition's factory. Replace 466 /// the descriptor's option with the newly created option. 467 /// -# If a definition is found and there is a formatted value, split 468 /// the value into vector of values and pass that into the definition's 469 /// factory. Replace the descriptor's option with the newly created option. 470 /// 471 /// @param cfg_def the user specified definitions to use 472 /// @param space the option space name of the option 473 /// @param opt_desc OptionDescriptor describing the option. 474 /// 475 /// @return True if the descriptor's option instance was replaced. 476 /// @throw InvalidOperation if the descriptor conveys a formatted value and 477 /// there is no definition matching the option code in the given space, or 478 /// if the definition factory invocation fails. 479 static bool createDescriptorOption(CfgOptionDefPtr cfg_def, const std::string& space, 480 OptionDescriptor& opt_desc); 481 482 /// @brief Merges this configuration to another configuration. 483 /// 484 /// This method iterates over the configuration items held in this 485 /// configuration and copies them to the configuration specified 486 /// as a parameter. If an item exists in the destination it is not 487 /// copied. 488 /// 489 /// @param [out] other Configuration object to merge to. 490 void mergeTo(CfgOption& other) const; 491 492 /// @brief Copies this configuration to another configuration. 493 /// 494 /// This method copies options configuration to another object. 495 /// 496 /// @param [out] other An object to copy the configuration to. 497 void copyTo(CfgOption& other) const; 498 499 /// @brief Appends encapsulated options to top-level options. 500 /// 501 /// This method iterates over the top-level options (from "dhcp4" 502 /// and "dhcp6" option space) and checks which option spaces these 503 /// options encapsulate. For each encapsulated option space, the 504 /// options from this option space are appended to top-level options. 505 void encapsulate(); 506 507 /// @brief Returns all options for the specified option space. 508 /// 509 /// This method will not return vendor options, i.e. having option space 510 /// name in the format of "vendor-X" where X is 32-bit unsigned integer. 511 /// See @c getAll(uint32_t) for vendor options. 512 /// 513 /// @param option_space Name of the option space. 514 /// 515 /// @return Pointer to the container holding returned options. This 516 /// container is empty if no options have been found. 517 OptionContainerPtr getAll(const std::string& option_space) const; 518 519 /// @brief Returns vendor options for the specified vendor id. 520 /// 521 /// @param vendor_id Vendor id for which options are to be returned. 522 /// 523 /// @return Pointer to the container holding returned options. This 524 /// container is empty if no options have been found. 525 OptionContainerPtr getAll(const uint32_t vendor_id) const; 526 527 /// @brief Returns option for the specified key and option code. 528 /// 529 /// The key should be a string, in which case it specifies an option space 530 /// name, or an uint32_t value, in which case it specifies a vendor 531 /// identifier. 532 /// 533 /// @note If there are multiple options with the same key, only one will 534 /// be returned. No indication will be given of the presence of others, 535 /// and the instance returned is not determinable. 536 /// 537 /// @param key Option space name or vendor identifier. 538 /// @param option_code Code of the option to be returned. 539 /// @tparam Selector one of: @c std::string or @c uint32_t 540 /// 541 /// @return Descriptor of the option. If option hasn't been found, the 542 /// descriptor holds NULL option. 543 template<typename Selector> get(const Selector & key,const uint16_t option_code)544 OptionDescriptor get(const Selector& key, 545 const uint16_t option_code) const { 546 547 // Check for presence of options. 548 OptionContainerPtr options = getAll(key); 549 if (!options || options->empty()) { 550 return (OptionDescriptor(false)); 551 } 552 553 // Some options present, locate the one we are interested in. 554 const OptionContainerTypeIndex& idx = options->get<1>(); 555 OptionContainerTypeIndex::const_iterator od_itr = idx.find(option_code); 556 if (od_itr == idx.end()) { 557 return (OptionDescriptor(false)); 558 } 559 560 return (*od_itr); 561 } 562 563 /// @brief Deletes option for the specified option space and option code. 564 /// 565 /// If the option is encapsulated within some non top level option space, 566 /// it is also deleted from all option instances encapsulating this 567 /// option space. 568 /// 569 /// @param option_space Option space name. 570 /// @param option_code Code of the option to be returned. 571 /// 572 /// @return Number of deleted options. 573 size_t del(const std::string& option_space, const uint16_t option_code); 574 575 /// @brief Deletes vendor option for the specified vendor id. 576 /// 577 /// @param vendor_id Vendor identifier. 578 /// @param option_code Option code. 579 /// 580 /// @return Number of deleted options. 581 size_t del(const uint32_t vendor_id, const uint16_t option_code); 582 583 /// @brief Deletes all options having a given database id. 584 /// 585 /// Note that there are cases when there will be multiple options 586 /// having the same id (typically id of 0). When configuration backend 587 /// is in use it sets the unique ids from the database. In cases when 588 /// the configuration backend is not used, the ids default to 0. 589 /// Passing the id of 0 would result in deleting all options that were 590 /// not added via the database. 591 /// 592 /// Both regular and vendor specific options are deleted with this 593 /// method. 594 /// 595 /// This method internally calls @c encapsulate() after deleting 596 /// options having the given id. 597 /// 598 /// @param id Identifier of the options to be deleted. 599 /// 600 /// @return Number of deleted options. Note that if a single option 601 /// instance is encapsulated by multiple options it adds 1 to the 602 /// number of deleted options even though the same instance is 603 /// deleted from multiple higher level options. 604 size_t del(const uint64_t id); 605 606 /// @brief Returns a list of configured option space names. 607 /// 608 /// The returned option space names exclude vendor option spaces, 609 /// such as "vendor-1234". These are returned by the 610 /// @ref getVendorIdsSpaceNames. 611 /// 612 /// @return List comprising option space names. getOptionSpaceNames()613 std::list<std::string> getOptionSpaceNames() const { 614 return (options_.getOptionSpaceNames()); 615 } 616 617 /// @brief Returns a list of all configured vendor identifiers. getVendorIds()618 std::list<uint32_t> getVendorIds() const { 619 return (vendor_options_.getOptionSpaceNames()); 620 } 621 622 /// @brief Returns a list of option space names for configured vendor ids. 623 /// 624 /// For each vendor-id the option space name returned is constructed 625 /// as "vendor-XYZ" where XYZ is a @c uint32_t value without leading 626 /// zeros. 627 /// 628 /// @return List comprising option space names for vendor options. 629 std::list<std::string> getVendorIdsSpaceNames() const; 630 631 /// @brief Unparse a configuration object 632 /// 633 /// @return a pointer to unparsed configuration 634 virtual isc::data::ElementPtr toElement() const; 635 636 /// @brief Unparse a configuration object with optionally including 637 /// the metadata. 638 /// 639 /// @param include_metadata boolean value indicating if the metadata 640 /// should be included (if true) or not (if false). 641 /// 642 /// @return A pointer to the unparsed configuration. 643 isc::data::ElementPtr 644 toElementWithMetadata(const bool include_metadata) const; 645 646 private: 647 648 /// @brief Appends encapsulated options to the options in an option space. 649 /// 650 /// This method appends sub-options to the options belonging to the 651 /// particular option space. For example: if the option space "foo" 652 /// is specified, this function will go over all options belonging to 653 /// "foo" and will check which option spaces they encapsulate. For each 654 /// such option it will retrieve options for these option spaces and append 655 /// as sub-options to options belonging to "foo". 656 /// 657 /// @param option_space Name of the option space containing option to 658 /// which encapsulated options are appended. 659 void encapsulateInternal(const std::string& option_space); 660 661 /// @brief Appends encapsulated options from the option space encapsulated 662 /// by the specified option. 663 /// 664 /// This method will go over all options belonging to the encapsulated space 665 /// and will check which option spaces they encapsulate recursively, 666 /// adding these options to the current option 667 /// 668 /// @param option which encapsulated options. 669 void encapsulateInternal(const OptionPtr& option); 670 671 /// @brief Merges data from two option containers. 672 /// 673 /// This method merges options from one option container to another 674 /// option container. This function is templated because containers 675 /// may use different type of selectors. For non-vendor options 676 /// the selector is of the @c std::string type, for vendor options 677 /// the selector is of the @c uint32_t type. 678 /// 679 /// @param src_container Reference to a container from which the data 680 /// will be merged. 681 /// @param [out] dest_container Reference to a container to which the 682 /// data will be merged. 683 /// @tparam Type of the selector: @c std::string or @c uint32_t. 684 template <typename Selector> 685 void mergeInternal(const OptionSpaceContainer<OptionContainer, 686 OptionDescriptor, Selector>& src_container, 687 OptionSpaceContainer<OptionContainer, 688 OptionDescriptor, Selector>& dest_container) const; 689 690 /// @brief Type of the container holding options grouped by option space. 691 typedef OptionSpaceContainer<OptionContainer, OptionDescriptor, 692 std::string> OptionSpaceCollection; 693 /// @brief Container holding options grouped by option space. 694 OptionSpaceCollection options_; 695 696 /// @brief Type of the container holding options grouped by vendor id. 697 typedef OptionSpaceContainer<OptionContainer, OptionDescriptor, 698 uint32_t> VendorOptionSpaceCollection; 699 /// @brief Container holding options grouped by vendor id. 700 VendorOptionSpaceCollection vendor_options_; 701 }; 702 703 /// @name Pointers to the @c CfgOption objects. 704 //@{ 705 /// @brief Non-const pointer. 706 typedef boost::shared_ptr<CfgOption> CfgOptionPtr; 707 708 /// @brief Const pointer. 709 typedef boost::shared_ptr<const CfgOption> ConstCfgOptionPtr; 710 711 /// @brief Const pointer list. 712 typedef std::list<ConstCfgOptionPtr> CfgOptionList; 713 714 //@} 715 716 } 717 } 718 719 #endif // CFG_OPTION_H 720