1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#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);
}
CRU_BASE_API inline std::ostream& 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
|