section.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. /*!
  2. *\file
  3. */
  4. // Config Class
  5. // Author: Charles Gruenwald III
  6. #include "section.hpp"
  7. #include <boost/algorithm/string.hpp>
  8. #include <iostream>
  9. namespace config
  10. {
  11. //! Section() Constructor for a root section
  12. Section::Section(const String & name, bool case_sensitive)
  13. :
  14. m_name(name),
  15. m_subSections(),
  16. m_keys(),
  17. m_parent(*this),
  18. m_isroot(true),
  19. m_case_sensitive(case_sensitive)
  20. {
  21. }
  22. //! Section() Constructor for a subsection
  23. Section::Section(Section const & parent, const String & name, bool case_sensitive)
  24. :
  25. m_name(name),
  26. m_subSections(),
  27. m_keys(),
  28. m_parent(parent),
  29. m_isroot(false),
  30. m_case_sensitive(case_sensitive)
  31. {
  32. }
  33. //! ~Section() Destructor
  34. Section::~Section()
  35. {
  36. m_subSections.clear();
  37. m_keys.clear();
  38. m_array_keys.clear();
  39. }
  40. //create a new section and add it to the subsection map
  41. Section & Section::addSubsection(const String & name_)
  42. {
  43. String iname(name_);
  44. if(!m_case_sensitive)
  45. boost::to_lower(iname);
  46. m_subSections.insert(std::pair< String, Section* >(iname, new Section(*this, name_, m_case_sensitive)));
  47. return *(m_subSections[iname]);
  48. }
  49. template <class V>
  50. const Key & Section::addKeyInternal(const String & name_, const V & value, uint64_t index)
  51. {
  52. //Make the key all lower-case if not case sensitive
  53. String iname(name_);
  54. if(!m_case_sensitive)
  55. boost::to_lower(iname);
  56. // Check for non-index version
  57. if (index == UINT64_MAX)
  58. {
  59. //Remove existing default key
  60. m_keys.erase(iname);
  61. //Remove overrides
  62. m_array_keys.erase(iname);
  63. m_keys.insert(std::pair< String, Key* >(iname, new Key(this->getFullPath(),name_,value)));
  64. return *(m_keys[iname]);
  65. }
  66. else
  67. {
  68. //Do not remove existing default key for override case
  69. UInt64 needed_size = index + 1;
  70. KeyArrayList::iterator found = m_array_keys.find(iname);
  71. if(found != m_array_keys.end())
  72. {
  73. std::vector<Key*> & arr = (*found).second;
  74. if (arr.size() < needed_size)
  75. {
  76. arr.resize(needed_size);
  77. }
  78. else
  79. {
  80. arr[index] = NULL;
  81. }
  82. }
  83. else
  84. {
  85. m_array_keys[iname] = std::vector<Key*>(needed_size);
  86. }
  87. m_array_keys[iname][index] = new Key(this->getFullPath(),name_,value);
  88. return *(m_array_keys[iname][index]);
  89. }
  90. }
  91. template const Key & Section::addKeyInternal(const String &, const String &, UInt64);
  92. template const Key & Section::addKeyInternal(const String &, const SInt64 &, UInt64);
  93. template const Key & Section::addKeyInternal(const String &, const double &, UInt64);
  94. //get a subkey of the given name
  95. // Not to be called unless the key exists (see hasKey())
  96. const Key & Section::getKey(const String & name_, uint64_t index)
  97. {
  98. String iname(name_);
  99. if(!m_case_sensitive)
  100. boost::to_lower(iname);
  101. if (index == UINT64_MAX)
  102. {
  103. // Default to using non-index version
  104. return *(m_keys[iname]);
  105. }
  106. else
  107. {
  108. if ( (m_array_keys.find(iname) != m_array_keys.end()) &&
  109. (m_array_keys[iname].size() >= (index+1)) &&
  110. (m_array_keys[iname][index] != NULL) )
  111. {
  112. // If we have the key as an override, use it
  113. return *(m_array_keys[iname][index]);
  114. }
  115. else
  116. {
  117. // Otherwise, return the value requested from the non-indexed version
  118. return *(m_keys[iname]);
  119. }
  120. }
  121. }
  122. //get a subsection of the given name
  123. const Section & Section::getSection(const String & name)
  124. {
  125. return getSection_unsafe(name);
  126. }
  127. //Unsafe version of the getSection function, this should only be used internally
  128. Section & Section::getSection_unsafe(const String & name)
  129. {
  130. String iname(name);
  131. if(!m_case_sensitive)
  132. boost::to_lower(iname);
  133. return *(m_subSections[iname]);
  134. }
  135. bool Section::hasSection(const String & name) const
  136. {
  137. String iname(name);
  138. if(!m_case_sensitive)
  139. boost::to_lower(iname);
  140. SectionList::const_iterator found = m_subSections.find(iname);
  141. return (found != m_subSections.end());
  142. }
  143. bool Section::hasKey(const String & name, UInt64 index) const
  144. {
  145. String iname(name);
  146. if(!m_case_sensitive)
  147. boost::to_lower(iname);
  148. if (index == UINT64_MAX)
  149. {
  150. if (m_keys.count(iname))
  151. return true;
  152. else if (m_array_keys.count(iname))
  153. return true;
  154. else
  155. return false;
  156. }
  157. else
  158. {
  159. return ( ( (m_array_keys.find(iname) != m_array_keys.end()) &&
  160. (m_array_keys.find(iname)->second.size() >= (index+1)) &&
  161. (m_array_keys.find(iname)->second[index] != NULL) )
  162. ||
  163. (m_keys.find(iname) != m_keys.end()) );
  164. }
  165. }
  166. const String Section::getFullPath() const
  167. {
  168. String path = "";
  169. if(isRoot())
  170. return path;
  171. if(getParent().isRoot())
  172. return getName();
  173. //create the path from the parent section and this section's name
  174. path = String(getParent().getFullPath()) + "/" + getName();
  175. return path;
  176. }
  177. }//end of namespace config