5#if !defined(__XTD_CORE_INTERNAL__)
6#error "Do not include this file: Internal use only"
10#include "../number_styles.hpp"
11#include "../types.hpp"
18void __throw_parse_format_exception(
const std::string& message,
const char* file,
xtd::uint32 line,
const char* func);
19void __throw_parse_overflow_exception(
const char* file,
xtd::uint32 line,
const char* func);
21template <
typename char_t>
22inline std::basic_string<char_t> __parse_remove_decorations(
const std::basic_string<char_t>& s,
xtd::number_styles styles) {
23 std::basic_string<char_t> str(s);
25 while (str.size() > 0 && (str[0] == 9 || str[0] == 10 || str[0] == 11 || str[0] == 12 || str[0] == 13 || str[0] == 32))
29 while (str.size() > 0 && (str[str.size() - 1] == 9 || str[str.size() - 1] == 10 || str[str.size() - 1] == 11 || str[str.size() - 1] == 12 || str[str.size() - 1] == 13 || str[str.size() - 1] == 32))
30 str.erase(str.size() - 1, 1);
40template <
typename char_t>
41inline int __parse_remove_signs(std::basic_string<char_t>& str,
xtd::number_styles styles) {
45 if (sign != 0) __throw_parse_format_exception(
"String contains more than one sign", __FILE__, __LINE__, __func__);
46 str = str.substr(1, str.size() - 1);
51 if (sign != 0) __throw_parse_format_exception(
"String contains more than one sign", __FILE__, __LINE__, __func__);
52 str = str.substr(1, str.size() - 1);
57 if (sign != 0) __throw_parse_format_exception(
"String contains more than one sign", __FILE__, __LINE__, __func__);
63 if (sign != 0) __throw_parse_format_exception(
"String contains more than one sign", __FILE__, __LINE__, __func__);
69 str = str.substr(1, str.size() - 2);
70 if (sign != 0) __throw_parse_format_exception(
"String contains more than one sign", __FILE__, __LINE__, __func__);
76template <
typename char_t>
77inline void __parse_check_valid_characters(
const std::basic_string<char_t>& str,
xtd::number_styles styles) {
78 std::basic_string<char_t> valid_characters = {
'0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
'8',
'9'};
81 if ((styles &
xtd::number_styles::allow_hex_specifier) ==
xtd::number_styles::allow_hex_specifier) valid_characters += std::basic_string<char_t> {
'A',
'B',
'C',
'D',
'E',
'F',
'a',
'b',
'c',
'd',
'e',
'f'};
87 if (valid_characters.find(c) == std::basic_string<char_t>::npos)
88 __throw_parse_format_exception(
"invalid character found", __FILE__, __LINE__, __func__);
92 size_t index = str.find(std::use_facet<std::numpunct<char_t>>(std::locale()).decimal_point());
93 if (index != std::basic_string<char_t>::npos && str.find(std::use_facet<std::numpunct<char_t>>(std::locale()).decimal_point(), index + 1) != std::basic_string<char_t>::npos)
94 __throw_parse_format_exception(
"invalid character found", __FILE__, __LINE__, __func__);
99 while ((index = str.find(std::use_facet<std::numpunct<char_t>>(std::locale()).thousands_sep(), index)) != std::basic_string<char_t>::npos) {
100 if (str[index - 1] == std::use_facet<std::numpunct<char_t>>(std::locale()).thousands_sep())
101 __throw_parse_format_exception(
"invalid character found", __FILE__, __LINE__, __func__);
107 size_t index = str.find(
'+');
108 if (index == std::basic_string<char_t>::npos) index = str.find(
'-');
109 if (index != std::basic_string<char_t>::npos && str[index - 1] !=
'e' && str[index - 1] !=
'E')
110 __throw_parse_format_exception(
"invalid character found", __FILE__, __LINE__, __func__);
114template <
typename value_t,
typename char_t>
115inline value_t __parse_floating_point(
const std::basic_string<char_t>& str,
int sign,
xtd::number_styles styles) {
118 result = std::stold(str,
nullptr);
120 std::stringstream ss(str);
121 ss.imbue(std::locale());
125 result = sign < 0 ? -result : result;
126 if (result < std::numeric_limits<value_t>::lowest() || result > std::numeric_limits<value_t>::max()) __throw_parse_overflow_exception(__FILE__, __LINE__, __func__);
127 return static_cast<value_t
>(result);
130template <
typename value_t,
typename char_t>
131inline value_t __parse_signed(
const std::basic_string<char_t>& str,
int base,
int sign,
xtd::number_styles styles) {
134 result = std::stoll(str,
nullptr, base);
136 std::stringstream ss(str);
137 ss.imbue(std::locale());
141 result = sign < 0 ? -result : result;
142 if (result < std::numeric_limits<value_t>::lowest() || result > std::numeric_limits<value_t>::max()) __throw_parse_overflow_exception(__FILE__, __LINE__, __func__);
143 return static_cast<value_t
>(result);
146template <
typename value_t,
typename char_t>
147inline value_t __parse_unsigned(
const std::basic_string<char_t>& str,
int base,
xtd::number_styles styles) {
148 unsigned long long result = 0;
150 result = std::stoull(str,
nullptr, base);
152 std::stringstream ss(str);
153 ss.imbue(std::locale());
157 if (result > std::numeric_limits<value_t>::max()) __throw_parse_overflow_exception(__FILE__, __LINE__, __func__);
158 return static_cast<value_t
>(result);
161template <
typename value_t,
typename char_t>
162inline value_t __parse_floating_point_number(
const std::basic_string<char_t>& s,
xtd::number_styles styles,
const std::locale& locale) {
168 for (
auto& c : lower_str)
169 c = static_cast<char>(std::tolower(
c));
170 if (s ==
"inf")
return std::numeric_limits<value_t>::infinity();
171 if (s ==
"-inf")
return -std::numeric_limits<value_t>::infinity();
172 if (s ==
"nan")
return std::numeric_limits<value_t>::quiet_NaN();
174 std::basic_string<char_t> str = __parse_remove_decorations(s, styles);
175 int sign = __parse_remove_signs(str, styles);
177 __parse_check_valid_characters(str, styles);
181 result = std::stold(str,
nullptr);
183 std::stringstream ss(str);
188 result = sign < 0 ? -result : result;
189 if (result < std::numeric_limits<value_t>::lowest() || result > std::numeric_limits<value_t>::max()) __throw_parse_overflow_exception(__FILE__, __LINE__, __func__);
190 return static_cast<value_t
>(result);
193template <
typename value_t,
typename char_t>
194inline value_t __parse_number(
const std::basic_string<char_t>& s,
xtd::number_styles styles) {
204 std::basic_string<char_t> str = __parse_remove_decorations(s, styles);
205 int sign = __parse_remove_signs(str, styles);
207 __parse_check_valid_characters(str, styles);
210 return __parse_signed<value_t>(str, base, sign, styles);
213template <
typename value_t,
typename char_t>
214inline value_t __parse_unsigned_number(
const std::basic_string<char_t>& s,
xtd::number_styles styles) {
224 std::basic_string<char_t> str = __parse_remove_decorations(s, styles);
225 if (__parse_remove_signs(str, styles) < 0) __throw_parse_format_exception(
"unsigned type can't have minus sign", __FILE__, __LINE__, __func__);
227 __parse_check_valid_characters(str, styles);
230 return __parse_unsigned<value_t>(str, base, styles);
233template<
typename value_t>
234value_t __parse_enum(
const std::string& str);
uint32_t uint32
Represents a 32-bit unsigned integer.
Definition uint32.hpp:23
size_t size
Represents a size of any object in bytes.
Definition size.hpp:23
number_styles
Determines the styles permitted in numeric string arguments that are passed to the xtd::parse and xtd...
Definition number_styles.hpp:16
@ allow_thousands
Indicates that the numeric string can have group separators, such as symbols that separate hundreds f...
@ allow_decimal_point
Indicates that the numeric string can have a decimal point. If the number_styles value includes the a...
@ allow_trailing_sign
Indicates that the numeric string can have a trailing sign. Valid trailing sign characters are determ...
@ allow_leading_sign
Indicates that the numeric string can have a leading sign.
@ none
Indicates that no style elements, such as leading or trailing white space, thousands separators,...
@ allow_parentheses
Indicates that the numeric string can have one pair of parentheses enclosing the number....
@ binary_number
Indicates that the allow_leading_white, allow_trailing_white, and allow_binary_specifier styles are u...
@ allow_exponent
Indicates that the numeric string can be in exponential notation. The allow_exponent flag allows the ...
@ allow_hex_specifier
Indicates that the numeric string represents a hexadecimal value. Valid hexadecimal values include th...
@ allow_octal_specifier
Indicates that the numeric string represents a octal value. Valid octal values include the numeric di...
@ allow_leading_white
Indicates that leading white-space characters can be present in the parsed string....
@ octal_number
Indicates that the allow_leading_white, allow_trailing_white, and allow_octal_specifier styles are us...
@ allow_trailing_white
Indicates that trailing white-space characters can be present in the parsed string....
@ allow_currency_symbol
Indicates that the numeric string can contain a currency symbol. Valid currency symbols are determine...
@ hex_number
Indicates that the allow_leading_white, allow_trailing_white, and allow_hex_specifier styles are used...
@ allow_binary_specifier
Indicates that the numeric string represents a binary value. Valid binary values include the numeric ...