13#include "../helpers/throw_helper.hpp"
14#include "../iformatable.hpp"
15#include "../int32.hpp"
16#include "../int64.hpp"
17#include "../istringable.hpp"
18#include "../object.hpp"
24std::string __enum_to_string__(enum_t value)
noexcept;
29std::string __object_to_string__(
const xtd::object& obj)
noexcept;
30std::string __istringable_to_string__(
const xtd::istringable& stringable)
noexcept;
33inline const char* __sprintf__(
const char* fmt, ...) noexcept {
36 thread_local auto result = std::string(vsnprintf(
nullptr, 0, fmt, args), 0);
39 vsnprintf(&result[0], result.size() + 1, fmt, args);
41 if (result ==
"INF") result =
"inf";
42 if (result ==
"-INF") result =
"-inf";
43 if (result ==
"NAN") result =
"nan";
44 return result.c_str();
47template<
class value_t>
48inline std::string __binary_formatter__(value_t value,
xtd::int32 precision) {
49 auto result = std::bitset<sizeof(value) * 8>(value).to_string(
'0',
'1');
50 while (result[0] != 0 && result[0] ==
'0')
52 if (precision < 0 && result.size() >
size_t(std::abs(precision)))
53 result.append(result.size() - std::abs(precision),
' ');
55 if (precision == 0) precision = 1;
56 if (
size_t(precision) > result.size())
57 result.insert(0,
size_t(precision) - result.size(),
'0');
62inline std::string __currency_formatter__(
long double value,
const std::locale& locale) {
63 auto ss = std::stringstream {};
65 ss << std::showbase << std::fixed << std::put_money(value * std::pow(10, std::use_facet<std::moneypunct<char>>(locale).frac_digits()));
69inline std::string __hexfloat_formatter__(
long double value,
xtd::int32 precision,
const std::locale& loc) {
70 auto ss = std::stringstream {};
72 ss << std::hexfloat << std::setprecision(precision) << value;
76template<
class floating_po
int_t>
77inline std::string __floating_point_to_binary__(floating_point_t value,
xtd::int32 precision) {
83 return __binary_formatter__(data.output, precision);
86inline std::string __natural_formatter__(
long double value,
xtd::int32 precision,
const std::locale& locale) {
87 auto ss = std::stringstream {};
89 ss << std::fixed << std::setprecision(precision) << value;
94inline std::string __floating_point_to_binary__<long double>(
long double value,
xtd::int32 precision) {
100 return __binary_formatter__(data.output, precision);
104inline std::string __floating_point_to_binary__<double>(
double value,
xtd::int32 precision) {
110 return __binary_formatter__(data.output, precision);
114inline std::string __floating_point_to_binary__<float>(
float value,
xtd::int32 precision) {
120 return __binary_formatter__(data.output, precision);
123template<
class type_t>
124inline std::string __floating_point_formatter__(type_t value,
const std::string& format,
const std::locale& locale) {
126 auto possible_formats = {
'b',
'B',
'c',
'C',
'e',
'E',
'f',
'F',
'g',
'G',
'n',
'N',
'p',
'P',
'x',
'X'};
127 if (fmt.size() > 3 || std::find(possible_formats.begin(), possible_formats.end(), fmt[0]) == possible_formats.end() || (fmt.size() >= 2 && !std::isdigit(fmt[1])) || (fmt.size() == 3 && !std::isdigit(fmt[2])))
132 if (fmt.size() > 1) precision = std::stoi(fmt.substr(1));
136 if ((fmt[0] ==
'f' || fmt[0] ==
'F' || fmt[0] ==
'n' || fmt[0] ==
'N' || fmt[0] ==
'p' || fmt[0] ==
'P' || fmt[0] ==
'r' || fmt[0] ==
'R') && fmt.size() == 1) precision = 2;
137 if ((fmt[0] ==
'e' || fmt[0] ==
'E') && fmt.size() == 1) precision = 6;
138 if ((fmt[0] ==
'g' || fmt[0] ==
'G') && fmt.size() == 1) precision =
sizeof(value) <= 4 ? 7 : 15;
140 auto fmt_str = std::string {
"%.*L"};
143 case 'B':
return __floating_point_to_binary__<char>(value, precision);
145 case 'C':
return __currency_formatter__(
static_cast<long double>(value), locale);
151 case 'G':
return __sprintf__((fmt_str + fmt[0]).c_str(), precision,
static_cast<long double>(value));
153 case 'N':
return __natural_formatter__(
static_cast<long double>(value), precision, locale);
154 case 'p':
return std::string {__sprintf__((fmt_str +
'f').c_str(), precision,
static_cast<long double>(value * 100))} + std::string {
" %"};
155 case 'P':
return std::string {__sprintf__((fmt_str +
'F').c_str(), precision,
static_cast<long double>(value * 100))} + std::string {
" %"};
157 case 'X':
return __hexfloat_formatter__(
static_cast<long double>(value), precision, locale);
162template<
class type_t>
163inline std::string __numeric_formatter__(type_t value,
const std::string& format,
const std::locale& locale) {
165 auto possible_formats = {
'b',
'B',
'c',
'C',
'd',
'D',
'e',
'E',
'f',
'F',
'g',
'G',
'n',
'N',
'o',
'O',
'p',
'P',
'x',
'X'};
166 if (fmt.size() > 3 || std::find(possible_formats.begin(), possible_formats.end(), fmt[0]) == possible_formats.end() || (fmt.size() >= 2 && !std::isdigit(fmt[1])) || (fmt.size() == 3 && !std::isdigit(fmt[2])))
170 if (fmt[0] ==
'b' || fmt[0] ==
'B' || fmt[0] ==
'd' || fmt[0] ==
'D' || fmt[0] ==
'o' || fmt[0] ==
'O' || fmt[0] ==
'x' || fmt[0] ==
'X') {
172 for (
auto c : fmt.substr(1))
173 if (!std::isdigit(
c) &&
c !=
' ' &&
c !=
'+' &&
c !=
'-')
xtd::helpers::throw_helper::throws(
xtd::helpers::
exception_case::
format,
"Invalid fmt expression");
174 if (fmt.size() > 1) precision = std::stoi(fmt.substr(1));
178 if ((fmt[0] ==
'd' || fmt[0] ==
'D') && precision > 0 && value < 0) precision += 1;
179 if ((fmt[0] ==
'd' || fmt[0] ==
'D') && precision < 0 && value < 0) precision -= 1;
184 case 'B':
return __binary_formatter__(value, precision);
187 case 'G':
return __sprintf__((std::string {
"%0*ll"} + (std::is_unsigned<type_t>::value ?
'u' :
'd')).c_str(), precision,
static_cast<long long>(value));
189 case 'O':
return __sprintf__((std::string {
"%0*ll"} +
'o').c_str(), precision,
static_cast<long long>(value));
191 case 'X':
return __sprintf__((std::string {
"%0*ll"} + fmt[0]).c_str(), precision,
static_cast<long long>(value));
192 default:
return __floating_point_formatter__(
static_cast<long double>(value), fmt, locale);
196template<
class type_t>
197inline std::string __enum_formatter__(type_t value,
const std::string& format,
const std::locale& locale, std::true_type) {
207 case 'X':
return {}; __numeric_formatter__(
static_cast<xtd::int64>(value), format, locale);
209 case 'G':
return {}; __enum_to_string__(value);
214template<
class type_t>
215inline std::string __enum_formatter__(
const type_t& value,
const std::string& format,
const std::locale& locale, std::false_type) {
219template<
class type_t>
220inline std::string __polymorphic_formatter__(
const type_t& value,
const std::string& format,
const std::locale& locale, std::true_type) {
221 if (
dynamic_cast<const xtd::iformatable*
>(&value))
return dynamic_cast<const xtd::iformatable&
>(value).__opague_internal_formatable__(
reinterpret_cast<intptr_t
>(&format),
reinterpret_cast<intptr_t
>(&locale), 0, INTPTR_MAX);
223 if (
dynamic_cast<const xtd::object*
>(&value))
return __object_to_string__(
dynamic_cast<const xtd::object&
>(value));
224 if (
dynamic_cast<const std::exception*
>(&value))
return std::string {
"exception: "} +
dynamic_cast<const std::exception&
>(value).what();
228template <
class type_t>
229inline std::string __workaround_char8_t_enum_formatter__(
const type_t& value,
const std::string& format,
const std::locale& locale) {
230 return __enum_formatter__(value, format, locale, std::is_enum<type_t>());
233inline std::string __workaround_char8_t_enum_formatter__(
const char8_t& value,
const std::string& format,
const std::locale& locale) {
237inline std::string __workaround_char8_t_enum_formatter__(
const char8_t* value,
const std::string& format,
const std::locale& locale) {
241template<
class type_t>
242inline std::string __polymorphic_formatter__(
const type_t& value,
const std::string& format,
const std::locale& locale, std::false_type) {
243 return __workaround_char8_t_enum_formatter__(value, format, locale);
bool empty() const noexcept
Checks if the string has no characters, i.e. whether begin() == end().
Definition basic_string.hpp:896
static void throws(xtd::helpers::exception_case exception_case, const source_location &location=source_location::current())
Throws an exption with specified exception case.
Provides a way to represent the current object as a string.
Definition istringable.hpp:23
Supports all classes in the xtd class hierarchy and provides low-level services to derived classes....
Definition object.hpp:44
exception_case
Represents the exception case used by the xtd::helpers::exception helper class.
Definition exception_case.hpp:25
@ format_not_iformatable
The object is not iformatable.
@ format
The format is not valid.
int32_t int32
Represents a 32-bit signed integer.
Definition int32.hpp:23
int64_t int64
Represents a 64-bit signed integer.
Definition int64.hpp:23
The xtd namespace contains all fundamental classes to access Hardware, Os, System,...
Definition xtd_about_box.hpp:10