aboutsummaryrefslogtreecommitdiff
path: root/include/cru/base/StringToNumberConverter.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/cru/base/StringToNumberConverter.h')
-rw-r--r--include/cru/base/StringToNumberConverter.h107
1 files changed, 107 insertions, 0 deletions
diff --git a/include/cru/base/StringToNumberConverter.h b/include/cru/base/StringToNumberConverter.h
new file mode 100644
index 00000000..758b26c8
--- /dev/null
+++ b/include/cru/base/StringToNumberConverter.h
@@ -0,0 +1,107 @@
+#pragma once
+#include "Base.h"
+#include "Bitmask.h"
+
+#include <cstddef>
+#include <ostream>
+
+namespace cru {
+namespace details {
+struct StringToNumberFlagTag {};
+} // namespace details
+
+using StringToNumberFlag = Bitmask<details::StringToNumberFlagTag>;
+
+struct StringToNumberFlags {
+ constexpr static StringToNumberFlag kAllowLeadingSpaces =
+ StringToNumberFlag::FromOffset(0);
+ constexpr static StringToNumberFlag kAllowTrailingSpaces =
+ StringToNumberFlag::FromOffset(1);
+ constexpr static StringToNumberFlag kAllowTrailingJunk =
+ StringToNumberFlag::FromOffset(2);
+ constexpr static StringToNumberFlag kAllowLeadingZeroForInteger =
+ StringToNumberFlag::FromOffset(3);
+ constexpr static StringToNumberFlag kThrowOnError =
+ StringToNumberFlag::FromOffset(4);
+};
+
+template <typename TResult>
+struct IStringToNumberConverter : virtual Interface {
+ virtual TResult Parse(const char* str, Index size,
+ Index* processed_characters_count) const = 0;
+
+ template <std::size_t Size>
+ TResult Parse(const char (&str)[Size],
+ Index* processed_characters_count) const {
+ return Parse(str, Size - 1, processed_characters_count);
+ }
+};
+
+struct CRU_BASE_API StringToIntegerResult {
+ StringToIntegerResult() = default;
+ StringToIntegerResult(bool negate, unsigned long long value)
+ : negate(negate), value(value) {}
+
+ bool negate;
+ unsigned long long value;
+};
+
+inline bool CRU_BASE_API operator==(const StringToIntegerResult& left,
+ const StringToIntegerResult& right) {
+ return left.negate == right.negate && left.value == right.value;
+}
+
+inline bool CRU_BASE_API operator!=(const StringToIntegerResult& left,
+ const StringToIntegerResult& right) {
+ return !(left == right);
+}
+
+inline std::ostream& CRU_BASE_API
+operator<<(std::ostream& stream, const StringToIntegerResult& result) {
+ return stream << "StringToIntegerConverterImplResult("
+ << (result.negate ? "-" : "") << result.value << ")";
+}
+
+/**
+ * \brief A converter that convert number into long long.
+ */
+struct CRU_BASE_API StringToIntegerConverter
+ : IStringToNumberConverter<StringToIntegerResult> {
+ public:
+ explicit StringToIntegerConverter(StringToNumberFlag flags, int base = 0)
+ : flags(flags), base(base) {}
+
+ bool CheckParams() const;
+
+ /**
+ * \brief Convert string to long long.
+ * \param str The string to convert.
+ * \param size The size of the string.
+ * \param processed_characters_count The number of characters that were
+ * processed. Or nullptr to not retrieve.
+ */
+ StringToIntegerResult Parse(const char* str, Index size,
+ Index* processed_characters_count) const override;
+ using IStringToNumberConverter<StringToIntegerResult>::Parse;
+
+ StringToNumberFlag flags;
+ /**
+ * \brief The base of the number used for parse or 0 for auto detect.
+ * \remarks Base can only be of range [2, 36] or 0. If base is 0, decimal is
+ * assumed by default ,or if str is started with "0x" or "0X" hexadecimal is
+ * assumed, or if str is started with a single "0" octoral is assumed, or if
+ * str is started with "0b" or "0B" binary is assumed. Otherwise it is an
+ * error.
+ */
+ int base;
+};
+
+struct CRU_BASE_API StringToFloatConverter {
+ StringToFloatConverter(StringToNumberFlag flags) : flags(flags) {}
+
+ double Parse(const char* str, Index size,
+ Index* processed_characters_count) const;
+
+ StringToNumberFlag flags;
+};
+} // namespace cru