logconfigptree.hpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. /*##############################################################################
  2. HPCC SYSTEMS software Copyright (C) 2021 HPCC Systems®.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. ############################################################################## */
  13. #ifndef _LOGCONFIGPTREE_HPP_
  14. #define _LOGCONFIGPTREE_HPP_
  15. #include "jptree.hpp"
  16. #include "jstring.hpp"
  17. #include "tokenserialization.hpp"
  18. namespace LogConfigPTree
  19. {
  20. /**
  21. * When relying upon a default value, check and report if the default value is not compatibile
  22. * with the requested value type. Most mismatches are errors. Some may be recorded as warnings
  23. * if a reasonable use case, e.g., defaulting an unsigned value to -1, exists to justify it.
  24. * In all cases, recorded findings should be addressed by either changing the default value or
  25. * casting the intended value correctly.
  26. */
  27. template <typename value_t, typename default_t>
  28. value_t applyDefault(const default_t& defaultValue, const char* xpath)
  29. {
  30. auto report = [&](bool isError)
  31. {
  32. StringBuffer msg;
  33. msg << "unexpected default value '" << defaultValue << "'";
  34. if (!isEmptyString(xpath))
  35. msg << " for configuration XPath '" << xpath << "'";
  36. if (isError)
  37. IERRLOG("%s", msg.str());
  38. else
  39. IWARNLOG("%s", msg.str());
  40. };
  41. if (std::is_integral<value_t>() == std::is_integral<default_t>())
  42. {
  43. if (std::is_signed<value_t>() == std::is_signed<default_t>())
  44. {
  45. if (defaultValue < std::numeric_limits<value_t>::min())
  46. report(true);
  47. else if (defaultValue > std::numeric_limits<value_t>::max())
  48. report(true);
  49. }
  50. else if (std::is_signed<value_t>())
  51. {
  52. if (defaultValue > std::numeric_limits<value_t>::max())
  53. report(true);
  54. }
  55. else if (!std::is_same<value_t, bool>()) // ignore boolean
  56. {
  57. if (defaultValue < 0 || defaultValue > std::numeric_limits<value_t>::max())
  58. report(false);
  59. }
  60. }
  61. else if (std::is_floating_point<value_t>() == std::is_floating_point<default_t>())
  62. {
  63. if (defaultValue < -std::numeric_limits<value_t>::max())
  64. report(true);
  65. else if (defaultValue > std::numeric_limits<value_t>::max())
  66. report(true);
  67. }
  68. else
  69. {
  70. report(false);
  71. }
  72. return value_t(defaultValue);
  73. }
  74. /**
  75. * Access a configuration property value, supporting legacy configurations that use element
  76. * content and newer configurations relying on attributes.
  77. *
  78. * Preferring new configurations instead of legacy, consider a request for an attribute to be
  79. * just that and a request for element content to be a request for either an attribute or an
  80. * element. A request for "A/@B" will be viewed as only a request for attribute B in element A,
  81. * while a request for "A/B" will be viewed first as a request for "A/@B" and as a request for
  82. * "A/B" only if "A/@B" is not found.
  83. */
  84. inline const char* queryConfigValue(const IPTree& node, const char* xpath)
  85. {
  86. const char* value = nullptr;
  87. if (!isEmptyString(xpath))
  88. {
  89. const char* delim = strrchr(xpath, '/');
  90. size_t attrIndex = (delim ? delim - xpath + 1 : 0);
  91. if (xpath[attrIndex] != '@')
  92. {
  93. StringBuffer altXPath(xpath);
  94. altXPath.insert(attrIndex, '@');
  95. value = node.queryProp(altXPath);
  96. if (value)
  97. return value;
  98. }
  99. value = node.queryProp(xpath);
  100. }
  101. return value;
  102. }
  103. inline const char* queryConfigValue(const IPTree* node, const char* xpath)
  104. {
  105. if (node)
  106. return queryConfigValue(*node, xpath);
  107. return nullptr;
  108. }
  109. inline bool getConfigValue(const IPTree& node, const char* xpath, StringBuffer& value)
  110. {
  111. const char* raw = queryConfigValue(node, value);
  112. if (raw)
  113. {
  114. value.set(raw);
  115. return true;
  116. }
  117. return false;
  118. }
  119. inline bool getConfigValue(const IPTree* node, const char* xpath, StringBuffer& value)
  120. {
  121. if (node)
  122. return getConfigValue(*node, xpath, value);
  123. return false;
  124. }
  125. template <typename value_t, typename default_t>
  126. value_t getConfigValue(const IPTree& node, const char* xpath, const default_t& defaultValue)
  127. {
  128. const char* raw = queryConfigValue(node, xpath);
  129. if (raw)
  130. {
  131. static TokenDeserializer deserializer;
  132. value_t value;
  133. if (deserializer(raw, value) == Deserialization_SUCCESS)
  134. return value;
  135. }
  136. return applyDefault<value_t>(defaultValue, xpath);
  137. }
  138. template <typename value_t>
  139. value_t getConfigValue(const IPTree& node, const char* xpath)
  140. {
  141. value_t defaultValue = value_t(0);
  142. return getConfigValue<value_t>(node, xpath, defaultValue);
  143. }
  144. template <typename value_t, typename default_t>
  145. value_t getConfigValue(const IPTree* node, const char* xpath, const default_t& defaultValue)
  146. {
  147. if (node)
  148. return getConfigValue<value_t>(*node, xpath, defaultValue);
  149. return applyDefault<value_t>(defaultValue, xpath);
  150. }
  151. template <typename value_t>
  152. value_t getConfigValue(const IPTree* node, const char* xpath)
  153. {
  154. if (node)
  155. return getConfigValue<value_t>(*node, xpath);
  156. return value_t(0);
  157. }
  158. } // namespace LogConfigPTree
  159. #endif // _LOGCONFIGPTREE_HPP_