simple_parser.h 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright (C) 2016 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 SIMPLE_PARSER_H
  7. #define SIMPLE_PARSER_H
  8. #include <cc/data.h>
  9. #include <vector>
  10. #include <string>
  11. #include <stdint.h>
  12. #include <limits>
  13. namespace isc {
  14. namespace data {
  15. /// This array defines a single entry of default values
  16. struct SimpleDefault {
  17. SimpleDefault(const char* name, isc::data::Element::types type, const char* value)
  18. :name_(name), type_(type), value_(value) {}
  19. std::string name_;
  20. const isc::data::Element::types type_;
  21. const char* value_;
  22. };
  23. /// This specifies all default values in a given scope (e.g. a subnet)
  24. typedef std::vector<SimpleDefault> SimpleDefaults;
  25. /// This defines a list of all parameters that are derived (or inherited) between
  26. /// contexts
  27. typedef std::vector<std::string> ParamsList;
  28. /// @brief A simple parser
  29. ///
  30. /// This class is intended to be a simpler replacement for @ref
  31. /// isc::dhcp::DhcpConfigParser. This class has been initially created to
  32. /// facilitate DHCPv4 and DHCPv6 servers' configuration parsing. Thus examples
  33. /// provided herein are related to DHCP configuration. Nevertheless, this is a
  34. /// generic class to be used in other modules too.
  35. ///
  36. /// The simplification comes from several factors:
  37. /// - no build/commit nonsense. There's a single step:
  38. /// CfgStorage parse(ConstElementPtr json)
  39. /// that converts JSON configuration into an object and returns it.
  40. /// - no state kept. This greatly simplifies the parsers (no contexts, no child
  41. /// parsers list, no separate storage for uint32, strings etc. In fact,
  42. /// this base class is purely static. However, some derived classes may store
  43. /// some state. Implementors are advised to store as little state as possible.
  44. /// - no optional parameters (all are mandatory). This simplifies the parser,
  45. /// but introduces a new step before parsing where we insert the default
  46. /// values into client configuration before parsing. This is actually a good
  47. /// thing, because we now have a clear picture of the default parameters as
  48. /// they're defined in a single place (the DhcpConfigParser had the defaults
  49. /// spread out in multiple files in multiple directories).
  50. class SimpleParser {
  51. public:
  52. /// @brief Derives (inherits) parameters from parent scope to a child
  53. ///
  54. /// This method derives parameters from the parent scope to the child,
  55. /// if there are no values specified in the child scope. For example,
  56. /// this method can be used to derive timers from global scope (e.g. for
  57. /// the whole DHCPv6 server) to a subnet scope. This method checks
  58. /// if the child scope doesn't have more specific values defined. If
  59. /// it doesn't, then the value from parent scope is copied over.
  60. ///
  61. /// @param parent scope to copy from (e.g. global)
  62. /// @param child scope to copy from (e.g. subnet)
  63. /// @param params names of the parameters to copy
  64. /// @return number of parameters copied
  65. static size_t deriveParams(isc::data::ConstElementPtr parent,
  66. isc::data::ElementPtr child,
  67. const ParamsList& params);
  68. /// @brief Sets the default values
  69. ///
  70. /// This method sets the default values for parameters that are not
  71. /// defined. The list of default values is specified by default_values.
  72. /// If not present, those will be inserted into the scope. If
  73. /// a parameter is already present, the default value will not
  74. /// be inserted.
  75. ///
  76. /// @param scope default values will be inserted here
  77. /// @param default_values list of default values
  78. /// @return number of parameters inserted
  79. static size_t setDefaults(isc::data::ElementPtr scope,
  80. const SimpleDefaults& default_values);
  81. /// @brief Sets the default values for all entries in a list
  82. ///
  83. /// This is a simple utility method that iterates over all
  84. /// parameters in a list and calls setDefaults for each
  85. /// entry.
  86. ///
  87. /// @param list list to be iterated over
  88. /// @param default_values list of default values
  89. /// @return number of parameters inserted
  90. static size_t setListDefaults(isc::data::ElementPtr list,
  91. const SimpleDefaults& default_values);
  92. /// @brief Utility method that returns position of an element
  93. ///
  94. /// It's mostly useful for logging. When any necessary parameter is
  95. /// missing (either parent is null or it doesn't contain specified
  96. /// name) ZERO_POSITION is returned.
  97. ///
  98. /// @param name position of that element will be returned
  99. /// @param parent parent element (optional)
  100. /// @return position of the element specified.
  101. static const data::Element::Position&
  102. getPosition(const std::string& name, const data::ConstElementPtr parent);
  103. protected:
  104. /// @brief Returns a string parameter from a scope
  105. ///
  106. /// Unconditionally returns a parameter. If the parameter is not there or
  107. /// is not of appropriate type, BadValue exception is thrown.
  108. ///
  109. /// @param scope specified parameter will be extracted from this scope
  110. /// @param name name of the parameter
  111. /// @return a string value of the parameter
  112. static std::string getString(isc::data::ConstElementPtr scope,
  113. const std::string& name);
  114. /// @brief Returns an integer parameter from a scope
  115. ///
  116. /// Unconditionally returns a parameter. If the parameter is not there or
  117. /// is not of appropriate type, BadValue exception is thrown.
  118. ///
  119. /// @param scope specified parameter will be extracted from this scope
  120. /// @param name name of the parameter
  121. /// @return an integer value of the parameter
  122. static int64_t getInteger(isc::data::ConstElementPtr scope,
  123. const std::string& name);
  124. /// @brief Returns a boolean parameter from a scope
  125. ///
  126. /// Unconditionally returns a parameter. If the parameter is not there or
  127. /// is not of appropriate type, BadValue exception is thrown.
  128. ///
  129. /// @param scope specified parameter will be extracted from this scope
  130. /// @param name name of the parameter
  131. /// @return a boolean value of the parameter
  132. static bool getBoolean(isc::data::ConstElementPtr scope,
  133. const std::string& name);
  134. /// @brief Returns an integer value with range checking
  135. ///
  136. /// This template should be instantied in parsers when useful
  137. ///
  138. /// @tparam int_type the integer type e.g. uint32_t
  139. /// @tparam out_of_range always @c isc::dhcp::DhcpConfigError
  140. /// @param name name of the parameter for error report
  141. /// @param value value of the parameter
  142. /// @throw isc::data::TypeError when the value is not an integer
  143. /// @throw out_of_range when the value does not fit in int_type
  144. template <typename int_type, class out_of_range> int_type
  145. extractInt(const std::string& name, ConstElementPtr value) const {
  146. int64_t val_int = value->intValue();
  147. if ((val_int < std::numeric_limits<int_type>::min()) ||
  148. (val_int > std::numeric_limits<int_type>::max())) {
  149. isc_throw(out_of_range, "out of range value (" << val_int
  150. << ") specified for parameter '" << name
  151. << "' (" << value->getPosition() << ")");
  152. }
  153. return (static_cast<int_type>(val_int));
  154. }
  155. };
  156. };
  157. };
  158. #endif