Mirror of espurna firmware for wireless switches and more
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

199 lines
4.5 KiB

  1. /*
  2. Part of SETTINGS MODULE
  3. Copyright (C) 2016-2019 by Xose Pérez <xose dot perez at gmail dot com>
  4. Copyright (C) 2019-2023 by Maxim Prokhorov <prokhorov dot max at outlook dot com>
  5. */
  6. #pragma once
  7. #include <Arduino.h>
  8. #include "settings_helpers.h"
  9. namespace espurna {
  10. namespace settings {
  11. namespace internal {
  12. namespace duration_convert {
  13. // A more loosely typed duration, so we could have a single type
  14. struct Pair {
  15. duration::Seconds seconds{};
  16. duration::Microseconds microseconds{};
  17. };
  18. struct Result {
  19. Pair value;
  20. bool ok { false };
  21. };
  22. template <typename T, typename Rep = typename T::rep, typename Period = typename T::period>
  23. std::chrono::duration<Rep, Period> to_chrono_duration(Pair result) {
  24. using Type = std::chrono::duration<Rep, Period>;
  25. return std::chrono::duration_cast<Type>(result.seconds)
  26. + std::chrono::duration_cast<Type>(result.microseconds);
  27. }
  28. // Attempt to parse the given string with the specific ratio
  29. // Same as chrono, std::ratio<1> is a second
  30. Result parse(StringView, int num, int den);
  31. template <intmax_t Num, intmax_t Den>
  32. Result parse(StringView view, std::ratio<Num, Den>) {
  33. return parse(view, Num, Den);
  34. }
  35. template <typename T>
  36. T unchecked_parse(StringView view) {
  37. const auto result = parse(view, typename T::period{});
  38. if (result.ok) {
  39. return to_chrono_duration<T>(result.value);
  40. }
  41. return T{}.min();
  42. }
  43. } // namespace duration_convert
  44. template <typename T>
  45. T convert(const String& value);
  46. template <>
  47. float convert(const String& value);
  48. template <>
  49. double convert(const String& value);
  50. template <>
  51. signed char convert(const String& value);
  52. template <>
  53. short convert(const String& value);
  54. template <>
  55. int convert(const String& value);
  56. template <>
  57. long convert(const String& value);
  58. template <>
  59. bool convert(const String& value);
  60. template <>
  61. unsigned long convert(const String& value);
  62. template <>
  63. unsigned int convert(const String& value);
  64. template <>
  65. unsigned short convert(const String& value);
  66. template <>
  67. unsigned char convert(const String& value);
  68. template <>
  69. duration::Microseconds convert(const String&);
  70. template <>
  71. duration::Milliseconds convert(const String&);
  72. template <>
  73. duration::Seconds convert(const String&);
  74. template <>
  75. duration::Minutes convert(const String&);
  76. template <>
  77. duration::Hours convert(const String&);
  78. inline String serialize(uint8_t value, int base = 10) {
  79. return String(value, base);
  80. }
  81. inline String serialize(uint16_t value, int base = 10) {
  82. return String(value, base);
  83. }
  84. String serialize(uint32_t value, int base = 10);
  85. inline String serialize(unsigned long value, int base = 10) {
  86. return serialize(static_cast<uint32_t>(value), base);
  87. }
  88. inline String serialize(int16_t value, int base = 10) {
  89. return String(value, base);
  90. }
  91. inline String serialize(int32_t value, int base = 10) {
  92. return String(value, base);
  93. }
  94. inline String serialize(int8_t value, int base = 10) {
  95. return serialize(static_cast<int32_t>(value), base);
  96. }
  97. inline String serialize(long value, int base = 10) {
  98. return String(value, base);
  99. }
  100. inline String serialize(bool value) {
  101. return value ? PSTR("true") : PSTR("false");
  102. }
  103. inline String serialize(float value) {
  104. return String(value, 3);
  105. }
  106. inline String serialize(double value) {
  107. return String(value, 3);
  108. }
  109. String serialize(duration::Microseconds);
  110. String serialize(duration::Milliseconds);
  111. String serialize(duration::Seconds);
  112. String serialize(duration::Minutes);
  113. String serialize(duration::Hours);
  114. template <typename Container, typename T>
  115. T convert(const Container& options, const String& value, T defaultValue) {
  116. if (value.length()) {
  117. using espurna::settings::options::Enumeration;
  118. using UnderlyingType = typename Enumeration<T>::UnderlyingType;
  119. typename Enumeration<T>::Numeric numeric;
  120. numeric.check(value, convert<UnderlyingType>);
  121. for (auto it = std::begin(options); it != std::end(options); ++it) {
  122. if (numeric && ((*it).numeric() == numeric.value())) {
  123. return static_cast<T>(numeric.value());
  124. } else if (!numeric && ((*it) == value)) {
  125. return (*it).value();
  126. }
  127. }
  128. }
  129. return defaultValue;
  130. }
  131. template <typename Container, typename T>
  132. String serialize(const Container& options, T value) {
  133. String out;
  134. for (auto it = std::begin(options); it != std::end(options); ++it) {
  135. if ((*it).value() == value) {
  136. out = (*it).string().toString();
  137. break;
  138. }
  139. }
  140. return out;
  141. }
  142. } // namespace internal
  143. } // namespace settings
  144. } // namespace espurna