Skip to content

Commit

Permalink
Allow disabling floating point support (#1590)
Browse files Browse the repository at this point in the history
* Allow disabling floating point support

Add FMT_USE_FLOAT, FMT_USE_DOUBLE and FMT_USE_LONG_DOUBLE to allow a
user of the library to configure the float types they want to allow.
This is specially useful in embedded environements where code size is
important.

* Avoid conditional macros to disable float support

* Add is_supported_floating_point constexpr function

* Fix empty-body warning
  • Loading branch information
albaguirre authored Mar 20, 2020
1 parent 52d0e1b commit d3e6684
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
12 changes: 12 additions & 0 deletions include/fmt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,18 @@ struct int128_t {};
struct uint128_t {};
#endif

#ifndef FMT_USE_FLOAT
# define FMT_USE_FLOAT 1
#endif

#ifndef FMT_USE_DOUBLE
# define FMT_USE_DOUBLE 1
#endif

#ifndef FMT_USE_LONG_DOUBLE
# define FMT_USE_LONG_DOUBLE 1
#endif

// Casts a nonnegative integer to unsigned.
template <typename Int>
FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) {
Expand Down
32 changes: 31 additions & 1 deletion include/fmt/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -724,6 +724,13 @@ FMT_CONSTEXPR bool is_negative(T) {
return false;
}

template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
FMT_CONSTEXPR bool is_supported_floating_point(T) {
return (std::is_same<T, float>::value && FMT_USE_FLOAT) ||
(std::is_same<T, double>::value && FMT_USE_DOUBLE) ||
(std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE);
}

// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
// represent all values of T.
template <typename T>
Expand Down Expand Up @@ -1685,6 +1692,9 @@ template <typename Range> class basic_writer {

template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
void write(T value, format_specs specs = {}) {
if (const_check(!is_supported_floating_point(value))) {
return;
}
float_specs fspecs = parse_float_type_spec(specs);
fspecs.sign = specs.sign;
if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
Expand Down Expand Up @@ -1883,6 +1893,10 @@ class arg_formatter_base {

template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
iterator operator()(T value) {
if (const_check(!is_supported_floating_point(value))) {
FMT_ASSERT(false, "unsupported float argument type");
return out();
}
writer_.write(value, specs_ ? *specs_ : format_specs());
return out();
}
Expand Down Expand Up @@ -2923,9 +2937,25 @@ struct formatter<T, Char,
&specs_, internal::char_specs_checker<decltype(eh)>(specs_.type, eh));
break;
case internal::type::float_type:
if (internal::const_check(FMT_USE_FLOAT)) {
internal::parse_float_type_spec(specs_, eh);
} else {
FMT_ASSERT(false, "float support disabled");
}
break;
case internal::type::double_type:
if (internal::const_check(FMT_USE_DOUBLE)) {
internal::parse_float_type_spec(specs_, eh);
} else {
FMT_ASSERT(false, "double support disabled");
}
break;
case internal::type::long_double_type:
internal::parse_float_type_spec(specs_, eh);
if (internal::const_check(FMT_USE_LONG_DOUBLE)) {
internal::parse_float_type_spec(specs_, eh);
} else {
FMT_ASSERT(false, "long double support disabled");
}
break;
case internal::type::cstring_type:
internal::handle_cstring_type_spec(
Expand Down

0 comments on commit d3e6684

Please sign in to comment.