config.hpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. #ifndef CONFIG_HPP
  2. #define CONFIG_HPP
  3. /*!
  4. *\file config.hpp
  5. * This file contains most of the interface for the external->in memory configuration management interface.
  6. * There is a Config class which is the main interface to the outside world for loading files, getting and
  7. * setting values as well as saving the given configuration. This base class is then derived from for
  8. * the different given backends. This Config class has a root 'Section'. Each section has a list of
  9. * subsections and a list of keys. Each key actually contains the value.
  10. */
  11. // Config Class
  12. // Author: Charles Gruenwald III
  13. #include "fixed_types.h"
  14. #include "key.hpp"
  15. #include "section.hpp"
  16. #include "config_exceptions.hpp"
  17. #include <vector>
  18. #include <map>
  19. #include <iostream>
  20. namespace config
  21. {
  22. __attribute__ ((__noreturn__)) void Error(const char* msg, ...);
  23. //
  24. typedef std::vector < String > PathElementList;
  25. typedef std::pair<String,String> PathPair;
  26. /*! \brief Config: A class for managing the interface to persistent configuration entries defined at runtime.
  27. * This class is used to manage a configuration interface.
  28. * It is the base class for which different back ends will derive from.
  29. */
  30. class Config
  31. {
  32. public:
  33. Config(bool case_sensitive = false): m_case_sensitive(case_sensitive), m_root("", case_sensitive){}
  34. Config(const Section & root, bool case_sensitive = false): m_case_sensitive(case_sensitive), m_root(root, "", case_sensitive){}
  35. virtual ~Config(){}
  36. /*! \brief A function for saving the entire configuration
  37. * tree to the specified path.
  38. * This function is responsible for walking through the entire
  39. * configuration tree (starting at the root) and outputing an
  40. * appropriate text representation than can then be re-read by
  41. * an appropriate configuration class.
  42. * Note: In the case of a write-through situation (as is the case
  43. * with the windows registry), this function is unnecessary.
  44. */
  45. virtual void saveAs(const String & path){}
  46. /*! \brief A function to convert from external representation to in-memory representation
  47. * This function sets the member variable m_path and then calls the loadConfig() function which
  48. * must be implemented by the derived back-end implementation.
  49. * \param path - This is the path where we load the configuration from. This may either be a registry
  50. * path for the case of the ConfigRegistry interface or a file path in the case of a ConfigFile interface.
  51. * \exception FileNotFound - This exception is thrown if the ConfigFile interface is instructed to load
  52. * a file which does not exist.
  53. * \exception parseError - This exception is thrown on a malformed file with the ConfigFile interface.
  54. */
  55. void load(const String &path);
  56. /*! \brief A function which will save the in-memory representation to the external
  57. * representation that was specified with the load() function.
  58. */
  59. void Save(){saveAs(m_path);}
  60. void clear();
  61. bool hasKey(const String & path, UInt64 index = UINT64_MAX);
  62. //! A function that will save a given value to key at the specified path.
  63. virtual void set(const String & path, const String & new_value);
  64. /*!
  65. * \overload virtual void set(const String & path, SInt64 new_value);
  66. */
  67. virtual void set(const String & path, SInt64 new_value);
  68. /*!
  69. * \overload virtual void set(const String & path, double new_value);
  70. */
  71. virtual void set(const String & path, double new_value);
  72. //! Returns a reference to the section at the given path.
  73. const Section & getSection(const String & path);
  74. //! Returns a reference to the root section of the configuration tree.
  75. const Section & getRoot() {return m_root;}
  76. /*! \brief addSection() adds the specified path as a new section, creating each entry
  77. * in the path along the way.
  78. */
  79. const Section & addSection(const String & path);
  80. /*! \brief Look up the key at the given path, and return the value of that key as a bool.
  81. * \param path - Path for key to look up
  82. * \exception KeyNotFound is thrown if the specified path doesn't exist.
  83. */
  84. bool getBool(const String & path) { return getBoolArray(path, UINT64_MAX); }
  85. bool getBoolArray(const String & path, UInt64 index);
  86. // For bools, let's make an exception to the no defaults rule.
  87. // This enables us to model optional components that may live at different places (e.g. perf_model/*_cache),
  88. // but relieve the user from disabling all of them manually
  89. bool getBoolDefault(const String & path, bool defaultValue)
  90. {
  91. if (hasKey(path))
  92. return getBool(path);
  93. else
  94. return defaultValue;
  95. }
  96. /*! \brief Look up the key at the given path, and return the value of that key as a bool.
  97. * \param path - Path for key to look up
  98. * \exception KeyNotFound is thrown if the specified path doesn't exist.
  99. */
  100. SInt64 getInt(const String & path) { return getIntArray(path, UINT64_MAX); }
  101. SInt64 getIntArray(const String & path, UInt64 index);
  102. /*! \brief Look up the key at the given path, and return the value of that key as a bool.
  103. * \param path - Path for key to look up
  104. * \exception KeyNotFound is thrown if the specified path doesn't exist.
  105. */
  106. const String getString(const String & path) { return getStringArray(path, UINT64_MAX); }
  107. const String getStringArray(const String & path, UInt64 index);
  108. //! Same as getString()
  109. const String get(const String &path) { return getString(path); }
  110. /*! \brief Look up the key at the given path, and return the value of that key as a bool.
  111. * \param path - Path for key to look up
  112. * \exception KeyNotFound is thrown if the specified path doesn't exist.
  113. */
  114. double getFloat(const String & path) { return getFloatArray(path, UINT64_MAX); }
  115. double getFloatArray(const String & path, UInt64 index);
  116. /*! \brief Returns a string representation of the tree starting at the specified section
  117. * \param current The root of the tree for which we are creating a string representation.
  118. */
  119. String showTree(const Section & current, int depth = 0);
  120. //! \brief Returns a string representation of the loaded configuration tree
  121. String showFullTree() { return showTree(m_root); }
  122. /*! addKey() Adds the specified path as a new key (with the given value), creating each entry
  123. * in the path along the way.
  124. * \param path The path to the new key
  125. * \param new_key The value for the newly created key
  126. */
  127. const Key & addKey(const String & path, const String & new_key, UInt64 index = UINT64_MAX) { return addKeyInternal(path, new_key, index); }
  128. /*! \overload addKey()
  129. */
  130. const Key & addKey(const String & path, const SInt64 new_key, UInt64 index = UINT64_MAX) { return addKeyInternal(path, new_key, index); }
  131. /*! \overload addKey()
  132. */
  133. const Key & addKey(const String & path, const double new_key, UInt64 index = UINT64_MAX) { return addKeyInternal(path, new_key, index); }
  134. protected:
  135. bool m_case_sensitive;
  136. Section m_root;
  137. String m_path;
  138. virtual void loadConfig() = 0;
  139. Section & getSection_unsafe(String const& path);
  140. Section & getRoot_unsafe() { return m_root; };
  141. Key & getKey_unsafe(String const& path);
  142. private:
  143. template <class V>
  144. const Key & addKeyInternal(const String & path, const V & new_key, UInt64 index);
  145. const Key & getKey(const String & path, UInt64 index);
  146. template <class V>
  147. const Key & getKey(const String & path, const V &default_val, UInt64 index);
  148. //Utility function used to break the last word past the last /
  149. //from the base path
  150. static PathPair splitPath(const String & path);
  151. //This function splits the path up like the function above, but also allows you to
  152. //pass the path_elements vector in (for later traversal)
  153. static PathPair splitPathElements(const String & path, PathElementList & path_elements);
  154. //Utility function to determine if a given path is a leaf (i.e. it has no '/'s in it)
  155. static bool isLeaf(const String & path);
  156. };
  157. }//end of namespace config
  158. #endif //BL_CONFIG_HPP