option_space_container.h 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright (C) 2013-2015 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. #ifndef OPTION_SPACE_CONTAINER_H
  7. #define OPTION_SPACE_CONTAINER_H
  8. #include <list>
  9. #include <string>
  10. namespace isc {
  11. namespace dhcp {
  12. /// @brief Simple container for option spaces holding various items.
  13. ///
  14. /// This helper class is used to store items of various types
  15. /// that are grouped by option space names. Each option space is
  16. /// mapped to a container that holds items which specifically can
  17. /// be OptionDefinition objects or Subnet::OptionDescriptor structures.
  18. ///
  19. /// @tparam ContainerType of the container holding items within
  20. /// option space.
  21. /// @tparam ItemType type of the item being held by the container.
  22. /// @tparam Selector a string (for option spaces) or uint32_t (for vendor options)
  23. template<typename ContainerType, typename ItemType, typename Selector>
  24. class OptionSpaceContainer {
  25. public:
  26. /// Pointer to the container.
  27. typedef boost::shared_ptr<ContainerType> ItemsContainerPtr;
  28. /// @brief Indicates the container is empty
  29. ///
  30. /// @return true when the container is empty
  31. bool empty() const {
  32. return (option_space_map_.empty());
  33. }
  34. /// @brief Adds a new item to the option_space.
  35. ///
  36. /// @param item reference to the item being added.
  37. /// @param option_space name or vendor-id of the option space
  38. void addItem(const ItemType& item, const Selector& option_space) {
  39. ItemsContainerPtr items = getItems(option_space);
  40. items->push_back(item);
  41. option_space_map_[option_space] = items;
  42. }
  43. /// @brief Get all items for the particular option space.
  44. ///
  45. /// @warning when there are no items for the specified option
  46. /// space an empty container is created and returned. However
  47. /// this container is not added to the list of option spaces.
  48. ///
  49. /// @param option_space name or vendor-id of the option space.
  50. ///
  51. /// @return pointer to the container holding items.
  52. ItemsContainerPtr getItems(const Selector& option_space) const {
  53. const typename OptionSpaceMap::const_iterator& items =
  54. option_space_map_.find(option_space);
  55. if (items == option_space_map_.end()) {
  56. return (ItemsContainerPtr(new ContainerType()));
  57. }
  58. return (items->second);
  59. }
  60. /// @brief Get a list of existing option spaces.
  61. ///
  62. /// @return a list of option spaces.
  63. ///
  64. /// @todo This function is likely to be removed once
  65. /// we create a structore of OptionSpaces defined
  66. /// through the configuration manager.
  67. std::list<Selector> getOptionSpaceNames() const {
  68. std::list<Selector> names;
  69. for (typename OptionSpaceMap::const_iterator space =
  70. option_space_map_.begin();
  71. space != option_space_map_.end(); ++space) {
  72. names.push_back(space->first);
  73. }
  74. return (names);
  75. }
  76. /// @brief Remove all items from the container.
  77. void clearItems() {
  78. option_space_map_.clear();
  79. }
  80. /// @brief Check if two containers are equal.
  81. ///
  82. /// This method checks if option space container contains exactly
  83. /// the same selectors and that there are exactly the same items
  84. /// added for each selector. The order of items doesn't matter.
  85. ///
  86. /// @param other Other container to compare to.
  87. ///
  88. /// @return true if containers are equal, false otherwise.
  89. bool equals(const OptionSpaceContainer& other) const {
  90. for (typename OptionSpaceMap::const_iterator it =
  91. option_space_map_.begin(); it != option_space_map_.end();
  92. ++it) {
  93. typename OptionSpaceMap::const_iterator other_it =
  94. other.option_space_map_.find(it->first);
  95. if (other_it == other.option_space_map_.end()) {
  96. return (false);
  97. }
  98. // If containers have different sizes it is an indication that
  99. // they are unequal.
  100. if (it->second->size() != other_it->second->size()) {
  101. return (false);
  102. }
  103. // If they have the same sizes, we have to compare each element.
  104. for (typename ContainerType::const_iterator items_it =
  105. it->second->begin();
  106. items_it != it->second->end(); ++items_it) {
  107. bool match_found = false;
  108. for (typename ContainerType::const_iterator other_items_it =
  109. other_it->second->begin();
  110. other_items_it != other_it->second->end();
  111. ++other_items_it) {
  112. if (items_it->equals(*other_items_it)) {
  113. match_found = true;
  114. break;
  115. }
  116. }
  117. if (!match_found) {
  118. return (false);
  119. }
  120. }
  121. }
  122. return (true);
  123. }
  124. private:
  125. /// A map holding container (option space name or vendor-id is the key).
  126. typedef std::map<Selector, ItemsContainerPtr> OptionSpaceMap;
  127. OptionSpaceMap option_space_map_;
  128. };
  129. } // end of isc::dhcp namespace
  130. } // end of isc namespace
  131. #endif // OPTION_SPACE_CONTAINER_H